// DDS.c
// DDS-routines
// Pros 2008


#define FSEL0         0x6000
#define FSEL1         0x6800
#define DDS_STOP      0xF800
#define DDS_START     0xC000
#define SET_SYNC      0xB000
#define FREG0_L_LSB   0x3000
#define FREG0_L_MSB   0x2100
#define FREG0_H_LSB   0x3200
#define FREG0_H_MSB   0x2300
#define FREG1_MASK    0x0400
#define PHASE0_L_LSB   0x1800
#define PHASE0_L_MSB   0x0900
#define PHASE0_H_LSB   0x1A00
#define PHASE0_H_MSB   0x0B00


void DDS_WRITE(unsigned int data)
{
    char cnt;

    sbi(DDS_C_PORTDDS_CLK);                                   // CLK hoog
    cbi(DDS_E_PORTDDS_EN);                                    // FSYNC laag
    delay(5);

    for (cnt = 0cnt < 16cnt++) {
        if ((data & 0x8000) == 0) {
            cbi(DDS_D_PORTDDS_D);
        } else {
            sbi(DDS_D_PORTDDS_D);
        }
        delay(5);
        cbi(DDS_C_PORTDDS_CLK);                               // CLK laag
        data = data << 1;
        delay(5);
        sbi(DDS_C_PORTDDS_CLK);                               // CLK hoog
    }
    sbi(DDS_E_PORTDDS_EN);                                    // FSYNC hoog
    delay(5);
}


// Stel een nieuwe dds_frequentie in.
// Om zonder haperen over te gaan van de ene naar de andere frequentie,
// plaatsen we de nieuwe gegevens in het frequentie-register dat momenteel
// niet in gebruik is, waarna we switchen
void FREQ_WORD_WRITE(unsigned long freq_word)
{
    unsigned int BYTE;

    if (FSEL == 0) {
        FSEL = FREG1_MASK;
    } else {
        FSEL = 0;
    }

    BYTE = (unsigned int) (freq_word & 0x000000FF);
    DDS_WRITE(FREG0_L_LSB | FSEL | BYTE);                       // FREG-L-LSB in defer-register
    BYTE = (unsigned int) ((freq_word >> 8) & 0x000000FF);
    DDS_WRITE(FREG0_L_MSB | FSEL | BYTE);                       // FREG-L-MSB + defer-register
    BYTE = (unsigned int) ((freq_word >> 16) & 0x000000FF);
    DDS_WRITE(FREG0_H_LSB | FSEL | BYTE);                       // FREG-H-LSB in defer-register
    BYTE = (unsigned int) ((freq_word >> 24) & 0x000000FF);
    DDS_WRITE(FREG0_H_MSB | FSEL | BYTE);                       // FREG-H-MSB + defer-register

    if (FSEL == FREG1_MASK) {
        DDS_WRITE(FSEL1);
    } else {
        DDS_WRITE(FSEL0);
    }
}


// Schrijf naar een PHASE-register
void PHASE_WORD_WRITE(unsigned long freq_word)
{
    unsigned int BYTE;

    BYTE = (unsigned int) (freq_word & 0x000000FF);
    DDS_WRITE(PHASE0_L_LSB | BYTE);                             // PHASE-L-LSB in defer-register
    BYTE = (unsigned int) ((freq_word >> 8) & 0x000000FF);
    DDS_WRITE(PHASE0_L_MSB | BYTE);                             // PHASE-L-MSB + defer-register
    BYTE = (unsigned int) ((freq_word >> 16) & 0x000000FF);
    DDS_WRITE(PHASE0_H_LSB | BYTE);                             // PHASE-H-LSB in defer-register
    BYTE = 0;                                                   // Er zijn maar 12 bits
    DDS_WRITE(PHASE0_H_MSB | BYTE);                             // PHASE-H-MSB + defer-register
}


// De gewenste frequentie wordt opgegeven in (Hz *100), en wordt eerst
// met 2 vermenigvuldigd, omdat de DDS gevolgd wordt door een tweedeler.
// DDS_word = ((DDS_frequency / MCLK) * PH_MAX + 0.5);
void set_DDS(double freq)
{
    freq *= 171.79869184;                                       // DDS_word = dds_frequentie * (((2^32 / 50000000) / 100) * 2)
    freq += 0.5;
    DDS_word = (unsigned longfreq;
    FREQ_WORD_WRITE(DDS_word);
}