Skip to content

Instantly share code, notes, and snippets.

@Pigu-A
Last active March 8, 2019 18:43
Show Gist options
  • Save Pigu-A/c541aad1ce4b43b37ca2387f36568b8b to your computer and use it in GitHub Desktop.
Save Pigu-A/c541aad1ce4b43b37ca2387f36568b8b to your computer and use it in GitHub Desktop.
when your avr compiler is very bad at 24-bit math
#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