update ATMlib

Optimized Assembly code saving more bytes and saving a few cycles
Moved and refactored assemby from ATMlib.h code to ATMlib.cpp
fix muteChannel() and unMuteChannel() so (un)mutes channel properly
Added C++ equivalent ISR code
This commit is contained in:
Mr.Blinky 2020-05-13 15:10:34 +02:00 committed by GitHub
parent 1cc93f05d7
commit 315c3c45e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 191 additions and 306 deletions

View File

@ -1,9 +1,192 @@
#include "ATMlib.h"
#ifndef AB_ALTERNATE_WIRING
ATMLIB_CONSTRUCT_ISR(OCR4A)
uint16_t __attribute__((used)) cia, __attribute__((used)) cia_count;
#ifdef __AVR_ARCH__
ISR(TIMER4_OVF_vect, ISR_NAKED) {
asm volatile(
"push r18 \n"
"lds r18, half \n" // half = !half;
"sbrc r18, 0 \n" // if (half) return;
"rjmp 2f \n"
"ldi r18, 0xFF \n"
"1: \n"
"sts half, r18 \n"
"pop r18 \n"
"reti \n"
"2: \n"
"push r0 \n"
"push r1 \n"
"push r2 \n"
"in r2, __SREG__ \n"
"push r30 \n"
"push r31 \n"
"ldi r30, lo8(osc) \n"
"ldi r31, hi8(osc) \n"
"ldi r18, 1 \n"
"ldd r0, Z+3*%[mul]+%[fre] \n" // uint16_t freq = osc[3].freq; //noise frequency
"ldd r1, Z+3*%[mul]+%[fre]+1 \n"
"add r0, r0 \n" // freq <<= 1;
"adc r1, r1 \n"
"sbrc r1, 7 \n" // if (freq & 0x8000) freq ^= 1;
"eor r0, r18 \n"
"sbrc r1, 6 \n" // if (freq & 0x4000) freq ^= 1;
"eor r0, r18 \n"
"std Z+3*%[mul]+%[fre], r0 \n" // osc[3].freq = freq;
"std Z+3*%[mul]+%[fre]+1, r1 \n"
"ldd r18, Z+3*%[mul]+%[vol] \n" // int8_t vol = osc[3].vol;
"sbrc r1, 7 \n" // if (freq & 0x8000) vol = -vol;
"neg r18 \n"
"mov r1, r18 \n"
"ldd r0, Z+0*%[mul]+%[fre] \n" // osc[0].phase += osc[0].freq; // update pulse phase
"ldd r18, Z+0*%[mul]+%[pha] \n"
"add r18, r0 \n"
"std Z+0*%[mul]+%[pha], r18 \n"
"ldd r0, Z+0*%[mul]+%[fre]+1 \n"
"ldd r18, Z+0*%[mul]+%[pha]+1 \n"
"adc r18, r0 \n"
"std Z+0*%[mul]+%[pha]+1, r18 \n"
"ldd r0, Z+0*%[mul]+%[vol] \n" // int8_t vol0 = osc[0].vol;
"cpi r18, 192 \n" // if (uint8_t(osc[0].phase >> 8) >= 192) vol0 = -vol0;
"brcs 3f \n"
"neg r0 \n"
"add r1, r0 \n" // int8_t vol += vol0;
"3: \n"
"ldd r18, Z+1*%[mul]+%[fre] \n" // osc[1].phase += osc[1].freq; // update square phase
"ldd r0, Z+1*%[mul]+%[pha] \n"
"add r0, r18 \n"
"std Z+1*%[mul]+%[pha], r0 \n"
"ldd r18, Z+1*%[mul]+%[fre]+1 \n"
"ldd r0, Z+1*%[mul]+%[pha]+1 \n"
"adc r0, r18 \n"
"std Z+1*%[mul]+%[pha]+1, r0 \n"
"ldd r18, Z+1*%[mul]+%[vol] \n" // int8_t vol1 = osc[1].vol;
"sbrc r0, 7 \n" // if (osc[1].phase & 0x8000) vol1 = -vol1;
"neg r18 \n"
"add r1, r18 \n" // vol += vol1;
"ldd r18, Z+2*%[mul]+%[fre] \n" // osc[2].phase += osc[2].freq;// update triangle phase
"ldd r0, Z+2*%[mul]+%[pha] \n"
"add r0, r18 \n"
"std Z+2*%[mul]+%[pha], r0 \n"
"ldd r0, Z+2*%[mul]+%[fre]+1 \n"
"ldd r18, Z+2*%[mul]+%[pha]+1 \n"
"adc r18, r0 \n"
"std Z+2*%[mul]+%[pha]+1, r18 \n"
// int8_t phase2 = osc[2].phase >> 8;
"ldd r30, Z+2*%[mul]+%[vol] \n" // int8_t vol2 = osc[2].vol;
"lds r31, pcm \n" // int8_t tmp = pcm + vol;
"add r31, r1 \n"
"sbrc r18, 7 \n" // if (phase2 < 0) phase2 = ~phase2;
"com r18 \n"
"lsl r18 \n" // phase2 <<= 1;
"subi r18, 128 \n" // phase2 -= 128;
"muls r18, r30 \n" // vol = ((phase2 * vol2) << 1) >> 8 + tmp;
"lsl r1 \n"
"add r1, r31 \n"
"sts %[reg], r1 \n" // reg = vol;
#ifdef AB_ALTERNATE_WIRING
"sts %[reg2], r1 \n" // reg2 = vol;
#endif
"lds r31, cia_count+1 \n" // if (--cia_count) return;
"lds r30, cia_count \n"
"sbiw r30, 1 \n"
"brne 4f \n"
"lds r31, cia+1 \n" // cia_count = cia;
"lds r30, cia \n"
"4: \n"
"sts cia_count+1, r31 \n"
"sts cia_count, r30 \n"
"brne 5f \n"
"sei \n" // sei();
"push r19 \n"
"push r20 \n"
"push r21 \n"
"push r22 \n"
"push r23 \n"
"push r24 \n"
"push r25 \n"
"push r26 \n"
"push r27 \n"
"clr r1 \n"
"call ATM_playroutine \n" // ATM_playroutine();
"pop r27 \n" // }
"pop r26 \n"
"pop r25 \n"
"pop r24 \n"
"pop r23 \n"
"pop r22 \n"
"pop r21 \n"
"pop r20 \n"
"pop r19 \n"
"5: \n"
"pop r31 \n"
"pop r30 \n"
"out __SREG__, r2 \n"
"pop r2 \n"
"pop r1 \n"
"pop r0 \n"
"ldi r18, 0x00 \n"
"rjmp 1b \n"
:
: [reg] "M" _SFR_MEM_ADDR(OCR4A),
#ifdef AB_ALTERNATE_WIRING
[reg2] "M" _SFR_MEM_ADDR(OCR4D),
#endif
[mul] "M" (sizeof(Oscillator)),
[pha] "M" (offsetof(Oscillator, phase)),
[fre] "M" (offsetof(Oscillator, freq)),
[vol] "M" (offsetof(Oscillator, vol))
);
}
#else
ATMLIB_CONSTRUCT_ISR(OCR4A,OCR4D)
ISR(TIMER4_OVF_vect)
{
half = !half;
if (half) return;
osc[2].phase += osc[2].freq; // update triangle phase
int8_t phase2 = osc[2].phase >> 8;
if (phase2 < 0) phase2 = ~phase2;
phase2 <<= 1;
phase2 -= 128;
int8_t vol = ((phase2 * int8_t(osc[2].vol)) << 1) >> 8;
osc[0].phase += osc[0].freq; // update pulse phase
int8_t vol0 = osc[0].vol;
if (osc[0].phase >= 0xC000) vol0 = -vol0;
vol += vol0;
osc[1].phase += osc[1].freq; // update square phase
int8_t vol1 = osc[1].vol;
if (osc[1].phase & 0x8000) vol1 = -vol1;
vol += vol1;
uint16_t freq = osc[3].freq; //noise frequency
freq <<= 1;
if (freq & 0x8000) freq ^= 1;
if (freq & 0x4000) freq ^= 1;
osc[3].freq = freq;
int8_t vol3 = osc[3].vol;
if (freq & 0x8000) vol3 = -vol3;
vol += vol3;
OCR4A = vol + pcm;
if (--cia_count) return;
cia_count = cia;
sei();
ATM_playroutine();
}
#endif
byte trackCount;
@ -162,11 +345,11 @@ void ATMsynth::playPause() {
// Toggle mute on/off on a channel, so it can be used for sound effects
// So you have to call it before and after the sound effect
void ATMsynth::muteChannel(byte ch) {
ChannelActiveMute += (1 << 0 );
ChannelActiveMute += (1 << ch );
}
void ATMsynth::unMuteChannel(byte ch) {
ChannelActiveMute &= (~(1 << 0 ));
ChannelActiveMute &= (~(1 << ch ));
}

View File

@ -51,303 +51,5 @@ extern osc_t osc[4];
uint16_t read_vle(const byte **pp);
static inline const byte *getTrackPointer(byte track);
extern void ATM_playroutine() asm("ATM_playroutine");
#ifndef AB_ALTERNATE_WIRING
#define ATMLIB_CONSTRUCT_ISR(TARGET_REGISTER) \
uint16_t __attribute__((used)) cia, __attribute__((used)) cia_count; \
ISR(TIMER4_OVF_vect, ISR_NAKED) { \
asm volatile( \
"push r2 " "\n\t" \
"in r2, __SREG__ " "\n\t" \
"push r18 " "\n\t" \
"lds r18, half " "\n\t" \
"com r18 " "\n\t" \
"sts half, r18 " "\n\t" \
"breq 1f " "\n\t" \
"rjmp 3f " "\n\t" \
"1: " "\n\t" \
"push r27 " "\n\t" \
"push r26 " "\n\t" \
"push r0 " "\n\t" \
"push r1 " "\n\t" \
\
"lds r18, osc+2*%[mul]+%[fre] " "\n\t" \
"lds r0, osc+2*%[mul]+%[pha] " "\n\t" \
"add r0, r18 " "\n\t" \
"sts osc+2*%[mul]+%[pha], r0 " "\n\t" \
"lds r18, osc+2*%[mul]+%[fre]+1" "\n\t" \
"lds r1, osc+2*%[mul]+%[pha]+1" "\n\t" \
"adc r1, r18 " "\n\t" \
"sts osc+2*%[mul]+%[pha]+1, r1 " "\n\t" \
\
"mov r27, r1 " "\n\t" \
"sbrc r27, 7 " "\n\t" \
"com r27 " "\n\t" \
"lsl r27 " "\n\t" \
"lds r26, osc+2*%[mul]+%[vol] " "\n\t" \
"subi r27, 128 " "\n\t" \
"muls r27, r26 " "\n\t" \
"lsl r1 " "\n\t" \
"mov r26, r1 " "\n\t" \
\
"lds r18, osc+0*%[mul]+%[fre] " "\n\t" \
"lds r0, osc+0*%[mul]+%[pha] " "\n\t" \
"add r0, r18 " "\n\t" \
"sts osc+0*%[mul]+%[pha], r0 " "\n\t" \
"lds r18, osc+0*%[mul]+%[fre]+1" "\n\t" \
"lds r1, osc+0*%[mul]+%[pha]+1" "\n\t" \
"adc r1, r18 " "\n\t" \
"sts osc+0*%[mul]+%[pha]+1, r1 " "\n\t" \
\
"mov r18, r1 " "\n\t" \
"lsl r18 " "\n\t" \
"and r18, r1 " "\n\t" \
"lds r27, osc+0*%[mul]+%[vol] " "\n\t" \
"sbrc r18, 7 " "\n\t" \
"neg r27 " "\n\t" \
"add r26, r27 " "\n\t" \
\
"lds r18, osc+1*%[mul]+%[fre] " "\n\t" \
"lds r0, osc+1*%[mul]+%[pha] " "\n\t" \
"add r0, r18 " "\n\t" \
"sts osc+1*%[mul]+%[pha], r0 " "\n\t" \
"lds r18, osc+1*%[mul]+%[fre]+1" "\n\t" \
"lds r1, osc+1*%[mul]+%[pha]+1" "\n\t" \
"adc r1, r18 " "\n\t" \
"sts osc+1*%[mul]+%[pha]+1, r1 " "\n\t" \
\
"lds r27, osc+1*%[mul]+%[vol] " "\n\t" \
"sbrc r1, 7 " "\n\t" \
"neg r27 " "\n\t" \
"add r26, r27 " "\n\t" \
\
"ldi r27, 1 " "\n\t" \
"lds r0, osc+3*%[mul]+%[fre] " "\n\t" \
"lds r1, osc+3*%[mul]+%[fre]+1" "\n\t" \
"add r0, r0 " "\n\t" \
"adc r1, r1 " "\n\t" \
"sbrc r1, 7 " "\n\t" \
"eor r0, r27 " "\n\t" \
"sbrc r1, 6 " "\n\t" \
"eor r0, r27 " "\n\t" \
"sts osc+3*%[mul]+%[fre], r0 " "\n\t" \
"sts osc+3*%[mul]+%[fre]+1, r1 " "\n\t" \
\
"lds r27, osc+3*%[mul]+%[vol] " "\n\t" \
"sbrc r1, 7 " "\n\t" \
"neg r27 " "\n\t" \
"add r26, r27 " "\n\t" \
\
"lds r27, pcm " "\n\t" \
"add r26, r27 " "\n\t" \
"sts %[reg], r26 " "\n\t" \
\
"lds r27, cia_count+1 " "\n\t" \
"lds r26, cia_count " "\n\t" \
"sbiw r26, 1 " "\n\t" \
"breq call_playroutine " "\n\t" \
"sts cia_count+1, r27 " "\n\t" \
"sts cia_count, r26 " "\n\t" \
"rjmp 2f " "\n\t" \
\
"call_playroutine: " "\n\t" \
\
"lds r27, cia+1 " "\n\t" \
"lds r26, cia " "\n\t" \
"sts cia_count+1, r27 " "\n\t" \
"sts cia_count, r26 " "\n\t" \
\
"sei " "\n\t" \
"push r19 " "\n\t" \
"push r20 " "\n\t" \
"push r21 " "\n\t" \
"push r22 " "\n\t" \
"push r23 " "\n\t" \
"push r24 " "\n\t" \
"push r25 " "\n\t" \
"push r30 " "\n\t" \
"push r31 " "\n\t" \
\
"clr r1 " "\n\t" \
"call ATM_playroutine " "\n\t" \
\
"pop r31 " "\n\t" \
"pop r30 " "\n\t" \
"pop r25 " "\n\t" \
"pop r24 " "\n\t" \
"pop r23 " "\n\t" \
"pop r22 " "\n\t" \
"pop r21 " "\n\t" \
"pop r20 " "\n\t" \
"pop r19 " "\n\t" \
"2: " "\n\t" \
"pop r1 " "\n\t" \
"pop r0 " "\n\t" \
"pop r26 " "\n\t" \
"pop r27 " "\n\t" \
"3: " "\n\t" \
"pop r18 " "\n\t" \
"out __SREG__, r2 " "\n\t" \
"pop r2 " "\n\t" \
"reti " "\n\t" \
: \
: [reg] "M" _SFR_MEM_ADDR(TARGET_REGISTER), \
[mul] "M" (sizeof(Oscillator)), \
[pha] "M" (offsetof(Oscillator, phase)), \
[fre] "M" (offsetof(Oscillator, freq)), \
[vol] "M" (offsetof(Oscillator, vol)) \
); \
}
#else
#define ATMLIB_CONSTRUCT_ISR(TARGET_REGISTER,TARGET_REGISTER2) \
uint16_t __attribute__((used)) cia, __attribute__((used)) cia_count; \
ISR(TIMER4_OVF_vect, ISR_NAKED) { \
asm volatile( \
"push r2 " "\n\t" \
"in r2, __SREG__ " "\n\t" \
"push r18 " "\n\t" \
"lds r18, half " "\n\t" \
"com r18 " "\n\t" \
"sts half, r18 " "\n\t" \
"breq 1f " "\n\t" \
"rjmp 3f " "\n\t" \
"1: " "\n\t" \
"push r27 " "\n\t" \
"push r26 " "\n\t" \
"push r0 " "\n\t" \
"push r1 " "\n\t" \
\
"lds r18, osc+2*%[mul]+%[fre] " "\n\t" \
"lds r0, osc+2*%[mul]+%[pha] " "\n\t" \
"add r0, r18 " "\n\t" \
"sts osc+2*%[mul]+%[pha], r0 " "\n\t" \
"lds r18, osc+2*%[mul]+%[fre]+1" "\n\t" \
"lds r1, osc+2*%[mul]+%[pha]+1" "\n\t" \
"adc r1, r18 " "\n\t" \
"sts osc+2*%[mul]+%[pha]+1, r1 " "\n\t" \
\
"mov r27, r1 " "\n\t" \
"sbrc r27, 7 " "\n\t" \
"com r27 " "\n\t" \
"lsl r27 " "\n\t" \
"lds r26, osc+2*%[mul]+%[vol] " "\n\t" \
"subi r27, 128 " "\n\t" \
"muls r27, r26 " "\n\t" \
"lsl r1 " "\n\t" \
"mov r26, r1 " "\n\t" \
\
"lds r18, osc+0*%[mul]+%[fre] " "\n\t" \
"lds r0, osc+0*%[mul]+%[pha] " "\n\t" \
"add r0, r18 " "\n\t" \
"sts osc+0*%[mul]+%[pha], r0 " "\n\t" \
"lds r18, osc+0*%[mul]+%[fre]+1" "\n\t" \
"lds r1, osc+0*%[mul]+%[pha]+1" "\n\t" \
"adc r1, r18 " "\n\t" \
"sts osc+0*%[mul]+%[pha]+1, r1 " "\n\t" \
\
"mov r18, r1 " "\n\t" \
"lsl r18 " "\n\t" \
"and r18, r1 " "\n\t" \
"lds r27, osc+0*%[mul]+%[vol] " "\n\t" \
"sbrc r18, 7 " "\n\t" \
"neg r27 " "\n\t" \
"add r26, r27 " "\n\t" \
\
"lds r18, osc+1*%[mul]+%[fre] " "\n\t" \
"lds r0, osc+1*%[mul]+%[pha] " "\n\t" \
"add r0, r18 " "\n\t" \
"sts osc+1*%[mul]+%[pha], r0 " "\n\t" \
"lds r18, osc+1*%[mul]+%[fre]+1" "\n\t" \
"lds r1, osc+1*%[mul]+%[pha]+1" "\n\t" \
"adc r1, r18 " "\n\t" \
"sts osc+1*%[mul]+%[pha]+1, r1 " "\n\t" \
\
"lds r27, osc+1*%[mul]+%[vol] " "\n\t" \
"sbrc r1, 7 " "\n\t" \
"neg r27 " "\n\t" \
"add r26, r27 " "\n\t" \
\
"ldi r27, 1 " "\n\t" \
"lds r0, osc+3*%[mul]+%[fre] " "\n\t" \
"lds r1, osc+3*%[mul]+%[fre]+1" "\n\t" \
"add r0, r0 " "\n\t" \
"adc r1, r1 " "\n\t" \
"sbrc r1, 7 " "\n\t" \
"eor r0, r27 " "\n\t" \
"sbrc r1, 6 " "\n\t" \
"eor r0, r27 " "\n\t" \
"sts osc+3*%[mul]+%[fre], r0 " "\n\t" \
"sts osc+3*%[mul]+%[fre]+1, r1 " "\n\t" \
\
"lds r27, osc+3*%[mul]+%[vol] " "\n\t" \
"sbrc r1, 7 " "\n\t" \
"neg r27 " "\n\t" \
"add r26, r27 " "\n\t" \
\
"lds r27, pcm " "\n\t" \
"add r26, r27 " "\n\t" \
"sts %[reg], r26 " "\n\t" \
"sts %[reg2], r26 " "\n\t" \
\
"lds r27, cia_count+1 " "\n\t" \
"lds r26, cia_count " "\n\t" \
"sbiw r26, 1 " "\n\t" \
"breq call_playroutine " "\n\t" \
"sts cia_count+1, r27 " "\n\t" \
"sts cia_count, r26 " "\n\t" \
"rjmp 2f " "\n\t" \
\
"call_playroutine: " "\n\t" \
\
"lds r27, cia+1 " "\n\t" \
"lds r26, cia " "\n\t" \
"sts cia_count+1, r27 " "\n\t" \
"sts cia_count, r26 " "\n\t" \
\
"sei " "\n\t" \
"push r19 " "\n\t" \
"push r20 " "\n\t" \
"push r21 " "\n\t" \
"push r22 " "\n\t" \
"push r23 " "\n\t" \
"push r24 " "\n\t" \
"push r25 " "\n\t" \
"push r30 " "\n\t" \
"push r31 " "\n\t" \
\
"clr r1 " "\n\t" \
"call ATM_playroutine " "\n\t" \
\
"pop r31 " "\n\t" \
"pop r30 " "\n\t" \
"pop r25 " "\n\t" \
"pop r24 " "\n\t" \
"pop r23 " "\n\t" \
"pop r22 " "\n\t" \
"pop r21 " "\n\t" \
"pop r20 " "\n\t" \
"pop r19 " "\n\t" \
"2: " "\n\t" \
"pop r1 " "\n\t" \
"pop r0 " "\n\t" \
"pop r26 " "\n\t" \
"pop r27 " "\n\t" \
"3: " "\n\t" \
"pop r18 " "\n\t" \
"out __SREG__, r2 " "\n\t" \
"pop r2 " "\n\t" \
"reti " "\n\t" \
: \
: [reg] "M" _SFR_MEM_ADDR(TARGET_REGISTER), \
[reg2] "M" _SFR_MEM_ADDR(TARGET_REGISTER2), \
[mul] "M" (sizeof(Oscillator)), \
[pha] "M" (offsetof(Oscillator, phase)), \
[fre] "M" (offsetof(Oscillator, freq)), \
[vol] "M" (offsetof(Oscillator, vol)) \
); \
}
#endif
#endif