/*! @file melody.c

  @brief   store  Never Gonna Give You Up
  @author  Lukas Fürderer
  @version V1.0
  @date    15.11.2020

This file contains the main app function and init.
*/

#include "melody.h"

// freq: wave duration as multiple of 40ns
// duration: total duration as multiple of 40ns
#define TONE(freq, duration) ((((uint32_t)freq & 0xffff) << 16) | (((uint32_t)duration / (uint32_t)freq) & 0xffff))

const uint32_t TACT = 2120 * 1000 * 25; // 2.12 seconds for one tact

const uint32_t GIS2 = 30098;
const uint32_t F = 35793;
const uint32_t DIS = 40177;
const uint32_t CIS = 45097;
const uint32_t C = 47778;
const uint32_t B = 53629;
const uint32_t GIS = 60197;

const uint32_t CALL = 0x10000;
const uint32_t RETURN = 0x20000;

const uint32_t refrain[];
const uint32_t quadrupel[];
const uint32_t *cpu32EntryPoint = refrain;

const uint32_t GOTO_REFRAIN = 0;
const uint32_t CALL_QUADRUPEL = CALL + 1;

const uint32_t *jumplabels[] = {
    refrain,
    quadrupel,
};
const uint32_t **cppu32JumpLabels = jumplabels;

const uint32_t quadrupel[] = {
    TONE(GIS, TACT / 16),
    TONE(B,   TACT / 16),
    TONE(CIS, TACT / 16),
    TONE(B,   TACT / 16),
    RETURN,
};

const uint32_t refrain[] = {
    CALL_QUADRUPEL,

    TONE(F,   TACT * 3 / 16),
    TONE(F,   TACT * 3 / 16),
    TONE(DIS, TACT * 3 / 8),
    CALL_QUADRUPEL,

    TONE(DIS, TACT * 3 / 16),
    TONE(DIS, TACT * 3 / 16),
    TONE(CIS, TACT * 3 / 16),
    TONE(C,   TACT / 16),
    TONE(B,   TACT / 8),
    CALL_QUADRUPEL,

    TONE(CIS, TACT / 4),
    TONE(DIS, TACT / 8),
    TONE(C,   TACT * 3 / 16),
    TONE(B,   TACT / 16),
    TONE(GIS, TACT / 4),
    TONE(GIS, TACT / 8),

    TONE(DIS, TACT / 4),
    TONE(CIS, TACT / 2),
    CALL_QUADRUPEL,

    TONE(F,   TACT * 3 / 16),
    TONE(F,   TACT * 3 / 16),
    TONE(DIS, TACT * 3 / 8),
    CALL_QUADRUPEL,

    TONE(GIS2,TACT / 4),
    TONE(C,   TACT / 8),
    TONE(CIS, TACT * 3 / 16),
    TONE(C,   TACT / 16),
    TONE(B,   TACT / 8),
    CALL_QUADRUPEL,

    TONE(CIS, TACT / 4),
    TONE(DIS, TACT / 8),
    TONE(C,   TACT * 3 / 16),
    TONE(B,   TACT / 16),
    TONE(GIS, TACT / 4),
    TONE(GIS, TACT / 8),

    TONE(DIS, TACT / 4),
    TONE(CIS, TACT / 2),

    GOTO_REFRAIN,
};
