#define TADR_BUZZER_ON  (TADR_SIO_BASE+TOFF_SIO_GPIO_OUT_SET)
#define TADR_BUZZER_OFF (TADR_SIO_BASE+TOFF_SIO_GPIO_OUT_CLR)
#define TADR_TIME_INTE  (TADR_TIMER_BASE+TOFF_TIMER_INTE+REG_ALIAS_SET)
#define TADR_TIME_INTD  (TADR_TIMER_BASE+TOFF_TIMER_INTE+REG_ALIAS_CLR)
#define TADR_CUR_TIME   (TADR_TIMER_BASE+TOFF_TIMER_TIMERAWL)
#define TADR_TIMEARM(o) (TADR_TIMER_BASE+TOFF_TIMER_ALARM0+((o) * 4))
省略
static const uint16_t Freq[] = {262, 294, 330, 349, 392, 440, 494, 523, 0}; ←音階の周波数テーブル
省略
int32_t  buzzer_freq = 0;
int32_t  music_no = -1;
uint32_t main_wrap_time = 1000000;
uint32_t buzzer_wrap_time = 0;
省略
eeprom_t music_data;  ←EEPROMのデータを保存する領域
uint8_t lcd_buf[2][12];

static inline void
set_timer_int(uint_t port, bool_t enable) ←タイマ割り込み許可，禁止関数
{
  if(enable)
    sil_wrw_mem((uint32_t *)TADR_TIME_INTE, (1 << port));
  else
    sil_wrw_mem((uint32_t *)TADR_TIME_INTD, (1 << port));
}
static inline void
set_next_alarm(uint_t port, uint32_t wrap_time) ←次のタイマ割り込みを設定する関数
{
  uint64_t delay_time = sil_rew_mem((uint32_t *)TADR_CUR_TIME) + wrap_time;
  sil_wrw_mem((uint32_t *)TADR_TIMEARM(port), (uint32_t)delay_time);
}
省略
/*
 *  演奏開始
 */
static void
start_music_timer(uint32_t freq)    ←演奏を開始する，freqがゼロの場合自動演奏，ゼロより大きい場合，周波数の音をならす
{
  if(freq == 0)
    music_no = 0;
  else
    buzzer_freq = freq;
  set_timer_int(APORT, true);
  play_music_handler();
}

/*
 *  ブザー・タイマ割り込み
 */
void
buzzer_timer_handler(void)  ←音階の周波数で割り込みが発生し，ブザーをON/OFFする
{
  uint32_t ints = sil_rew_mem((uint32_t *)(TADR_TIMER_BASE+TOFF_TIMER_INTS));
  /*
   *  割り込みクリア
   */
  sil_wrw_mem((uint32_t *)(TADR_TIMER_BASE+TOFF_TIMER_INTR), ints);

  /*
   *  リロード時間設定
   */
  if(buzzer_wrap_time != 0){
    set_next_alarm(BPORT, buzzer_wrap_time);
    sil_wrw_mem((uint32_t *)TADR_BUZZER_ON, (1<<BUZZER_PIN));
    sil_dly_nse(TOP_TIME*1000);
    sil_wrw_mem((uint32_t *)TADR_BUZZER_OFF, (1<<BUZZER_PIN));
  }
}

/*
 *  メイン・タイマ割り込み
 */
void
play_music_handler(void)    ←一音鳴らす周期で割り込みが発生する
{
  uint32_t ints = sil_rew_mem((uint32_t *)(TADR_TIMER_BASE+TOFF_TIMER_INTS));
  uint32_t freq = 0;

  /*
   *  割り込みクリア
   */
  sil_wrw_mem((uint32_t *)(TADR_TIMER_BASE+TOFF_TIMER_INTR), ints);

  if(buzzer_freq != 0){ ←次の周波数を取り出す
    freq = buzzer_freq;
    buzzer_freq = 0;
  }
  else if(music_no >= 0 && music_no < music_data.mcount){
    uint32_t fno = music_data.mbuffer[music_no] - '1';
    if(fno >= 0 && fno < 8)
      freq = Freq[fno];
    else
      freq = 1;
    music_no++;
  }
  else if(music_no == music_data.mcount)
    music_no = -1;
  sil_wrw_mem((uint32_t *)TADR_BUZZER_OFF, (1<<BUZZER_PIN));
  sil_dly_nse(500*1000);
  if(freq > 1){ ←次の周波数があるとき，BPORTタイマを起動
    buzzer_wrap_time = 1000000 / freq;
    set_timer_int(BPORT, true);
    set_next_alarm(APORT, main_wrap_time);
    set_next_alarm(BPORT, buzzer_wrap_time);
  }
  else if(freq == 1){   ←無音処理
    set_timer_int(BPORT, false);
    set_next_alarm(APORT, main_wrap_time);
  }
  else{ ←演奏停止
    set_timer_int(APORT, false);
    set_timer_int(BPORT, false);}
}
