/*
  Copyright (C) 2019 Tomonori IZUMI <izumi@ieee.org> All Rights Reserved.
*/

//#define _SOUNDCODE_TEST_

#include "soundcode.h"

void soundcode_play(const uint16_t code[]){
  int i,c,f,t;
  int8_t c1,c2;
  i=0;
  while (1) {
    c=pgm_read_word_near(code + i);
    c1= c    &0xf;
    c2=(c>>4)&0xf;
    t =(c>>8)&0xff;
    if (t==0) break;
    f=pgm_read_word_near(soundcode_freq + c1);
    c2=9-c2-soundcode_octave;
    f=(c2>=0)?(f>>c2):0;
    if (f>55 && f<10000)
      tone(soundcode_pin,f);
    else
      noTone(soundcode_pin);
    delay(soundcode_tempo*t);
    i++;
  }
  noTone(soundcode_pin);
}

void soundcode_playword(uint32_t code){
  int8_t i=32,c1=0,c2=0,d=0;
  int f;

  while (c2==0&&i>0) {/* assume octave code > 0 */
    i=i-4;
    c2=(code>>i)&0xf;
  }
  if (i<=0) return; /* no sound code */
  i=i-4;
  c1=(code>>i)&0xf;
  c2=9-c2-soundcode_octave;
  while (1) {
    if (d!=8) {
      f=pgm_read_word_near(soundcode_freq + c1);
      f=(c2>=0)?(f>>c2):0;
    } else {
      f=0; /* sclient */
    }
    if (f>55 && f<10000)
      tone(soundcode_pin,f);
    else
      noTone(soundcode_pin);
    delay(soundcode_tempo*3);
    noTone(soundcode_pin);
    delay(soundcode_tempo*1);

    if (i<=0) break;
    
    i=i-4;
    d=(code>>i)&0xf;
    if (d<8) {
      c1=c1+d;
      while (c1>=12) {
	c1=c1-12;
	c2=c2-1; // reversed
      }
    } else if (d>8){
      c1=c1-0x10+d;
      while (c1<0) {
	c1=c1+12;
	c2=c2+1; // reversed
      }
    }
    
  }
  
  return;
}

#ifdef _SOUNDCODE_TEST_

void setup() {
  soundcode_pin = 11;
  pinMode( soundcode_pin, OUTPUT );
}

void loop() {
  soundcode_playword(0x40345); /* A */
  delay(1000);
  soundcode_play(soundcode_test);
  delay(1000);
  soundcode_playword(0x40435); /* Am */
  delay(1000);
  soundcode_play(soundcode_chime);
  soundcode_play(soundcode_chime2);
  delay(1000);
  soundcode_play(soundcode_f1gp);
  delay(1000);
  soundcode_play(soundcode_go);
  delay(1000);
  soundcode_play(soundcode_failed);
  delay(1000);
  soundcode_playword(0x4000);
  delay(1000);
  soundcode_play(soundcode_eva);
  delay(1000);
  soundcode_playword(0x4084);
  delay(1000);
}

#endif
