Last active
March 8, 2019 18:43
-
-
Save Pigu-A/c541aad1ce4b43b37ca2387f36568b8b to your computer and use it in GitHub Desktop.
when your avr compiler is very bad at 24-bit math
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Arduino.h" | |
#include "SPI.h" | |
const uint8_t F[] = {57,57,57,57,77,102,128,153}; | |
const int8_t L[] = {1,3,5,7,9,11,13,15,-1,-3,-5,-7,-9,-11,-13,-15}; | |
const uint16_t MIN_Q = 127; | |
const uint16_t MAX_Q = 24576; | |
uint16_t qn; | |
int16_t xn; | |
void serialEvent() { | |
while (Serial.available()) { | |
uint8_t ad = (Serial.read() & 15); | |
/* convert ym2608 adpcm to float samples | |
xn += L[ad]*qn/8 | |
xn = clamp(xn,-32768,32767) | |
qn *= F[ad&7]/64 | |
qn = clamp(qn,MIN_Q,MAX_Q) | |
*/ | |
__asm__ volatile ( | |
"lds r12, %0\n\t" // xn | |
"lds r13, %0+1\n\t" | |
"lds r14, %1\n\t" // qn | |
"lds r15, %1+1\n\t" | |
"clr r18\n\t" // L[ad]*qn | |
"mov r19, r14\n\t" | |
"mulsu %2, r19\n\t" | |
"sbc r18, r18\n\t" | |
"movw r16, r0\n\t" | |
"mov r19, r15\n\t" | |
"mulsu %2, r19\n\t" | |
"add r17, r0\n\t" | |
"adc r18, r1\n\t" | |
"asr r18\n\t" // L[ad]*qn/8 | |
"ror r17\n\t" | |
"ror r16\n\t" | |
"asr r18\n\t" | |
"ror r17\n\t" | |
"ror r16\n\t" | |
"asr r18\n\t" | |
"ror r17\n\t" | |
"ror r16\n\t" | |
"clr r0\n\t" // xn+L[ad]*qn/8 | |
"sbrs r13, 7\n\t" | |
"com r0\n\t" | |
"add r16, r12\n\t" | |
"adc r17, r13\n\t" | |
"adc r18, r0\n\t" | |
"clr r0\n\t" // clamp(-32768,32767) | |
"cpi r17, 128\n\t" | |
"cpc r18, r0\n\t" | |
"brlt .lt\n\t" | |
"ldi r16, lo8(32767)\n\t" | |
"ldi r17, hi8(32767)\n\t" | |
"rjmp .ge\n" | |
".lt:\n\t" | |
"ldi r19, hi8(-32768)\n\t" | |
"cpi r16, 0\n\t" | |
"cpc r17, r19\n\t" | |
"ldi r19, -1\n\t" | |
"cpc r18, r19\n\t" | |
"brge .ge\n\t" | |
"ldi r16, lo8(-32768)\n\t" | |
"ldi r17, hi8(-32768)\n" | |
".ge:\n\t" | |
"sts %0, r16\n\t" // xn = | |
"sts %0+1, r17\n\t" | |
"clr r18\n\t" // F[ad&7]*qn | |
"mul %3, r14\n\t" | |
"movw r16, r0\n\t" | |
"mul %3, r15\n\t" | |
"add r17, r0\n\t" | |
"adc r18, r1\n\t" | |
"lsl r16\n\t" // F[ad&7]*qn/64 | |
"rol r17\n\t" | |
"rol r18\n\t" | |
"lsl r16\n\t" | |
"rol r17\n\t" | |
"rol r18\n\t" | |
// since maximum qn*F[ln]/64 term is 58752, | |
// there's no need to do special compare code here | |
"sts %1, r17\n\t" // qn = | |
"sts %1+1, r18" | |
: "+m" (xn), "+m" (qn) | |
: "a" (L[ad]), "r" (F[ad&7]) | |
: "cc", "r0", "r1", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19"); | |
if (qn < MIN_Q) qn = MIN_Q; | |
else if (qn < MAX_Q) qn = MAX_Q; | |
} | |
} | |
void setup() { | |
qn = MIN_Q; | |
xn = 0; | |
Serial.begin(142857); | |
} | |
void loop() { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment