#include <stdio.h>

#include <errno.h>

#include <math.h>


#define FSAMPLE     9600

#define TRUE        1

#define FALSE       !TRUE

#define KBSIGNAL    2001


typedef struct {

    short index;

    unsigned int data[64];

} FRAME;


typedef struct {

    short vco;

    short signsign;

    short vcofreq;

    short centerfreq;

    short lp1;

    short lp2;

    short sign;

    short clock;

    short phase;

    short diff;

    int byte;

    short bitcount;

    FRAME *rxbuf;

    short frame;

    short sintbl[256];

} DSP;


DSP *dsp;

int sighand();

int key = FALSE;

int quit = FALSE;


main(argc, argv)

int argc;

char *argv[];

{

    FRAME *rxbuf;

    int i, freq;

    unsigned char c;


    dsp = (DSP *)malloc(sizeof(DSP));


    freq = 1200;

    dsp->centerfreq = 0xffff*freq/FSAMPLE;


    for (i=0; i<256; i++) {

        dsp->sintbl[i] = 0x7fff*sin(2*PI*i/256);

    }

    

    rxbuf = (FRAME *)malloc(sizeof(FRAME));

    dsp->rxbuf = rxbuf;

    rxbuf->index = 0;


    dsp->bitcount = -1;


    intercept(sighand);

    _ss_ssig(0, KBSIGNAL);


    init(dsp);

    cls(0);


    do {

        

        /* process received frames */

        if (dsp->byte == 0x1acffc1d) {

            printf("sync found!\n");

        }

        

        if (dsp->frame) {

            dsp->frame = FALSE;

            for (i=0; i<64; i++) {

                printf("%08x\n", rxbuf->data[i]);

            }

        }


        if (key) {

            read(0, &c, 1);

            switch(c) {

            case 'q':

                quit = TRUE;

                break;

            case '+':

                freq += 50;

                break;

            case '-':

                freq -= 50;

                break;

            }


            dsp->centerfreq = 0xffff*freq/FSAMPLE;

            showfreq(freq);


            _ss_ssig(0, KBSIGNAL);

            key = FALSE;

        }


    } while (!quit);

    

    deinit();

}


trace(frm)

FRAME *frm;

{

    int i, len;

    

/*  len = frm->len;

    while (--len > 0) {

        putchar(frm->data[i++]);

        if (!(i%32))

            printf("\n");

    }

*/

}


showfreq(f)

{

    char str[80];

    

    sprintf(str, "center: %4d", f);

    cursor(0,0);

    prstr(str);

}


sighand(signal)

register int signal;

{

    switch(signal) {

        case KBSIGNAL:

            key = TRUE;

            break;


        default:

            deinit();

            exit(1);

    }

}


#asm


PADDR   equ     $05

PADR    equ     $11

TCR     equ     $21

CPRH    equ     $27

CPRM    equ     $29

CPRL    equ     $2B

TSR     equ     $35

ADC     equ     $100


oldvec  dc.l    1


init:   link    a5,#0

        movem.l d0-d2/a0-a3,-(sp)

        

        lea.l   irq6+6(pc),a0

        move.l  d0,(a0)


        lea.l   oldvec(pc),a0

        move.l  $78,(a0)

        lea.l   irq6(pc),a0

        move.l  a0,$78

        

        lea.l   $c01000,a0

        move.b  #$e0,TCR(a0)

        nop

        move.b  #00,CPRH(a0)

        nop

        move.b  #00,CPRM(a0)

        nop

        move.b  #25,CPRL(a0)

        nop

        move.b  #$e1,TCR(a0)

        

        movem.l (sp)+,d0-d2/a0-a3

        unlk    a5

        rts


deinit: movem.l a0,-(sp)

        lea.l   $c01000,a0

        move.b  #0,TCR(a0)

        lea.l   oldvec(pc),a0

        move.l  (a0),$78

        movem.l (sp)+,a0

        rts


irq6:   movem.l d0-d2/a0-a3,-(sp)


        movea.l #-1,a2

        

        lea.l   $c01000,a3

        move.b  #$01,TSR(a3)

        move    ADC(a3),d1

        andi    #$fff,d1

        subi    #$440,d1

*       asl     #2,d1

        

        move    d1,d2

        move    (a2),d0             vco in d0

        lsr     #8,d0               make word

        lsl     #1,d0               and even for offset

        add     #32,d0              offset to sin table

        muls    (a2,d0.w),d1    

        move    (a2)+,d0            

        move    (a2),d1             get previous sign in d1

        andi    #$8000,d2           new sign in d2

        move    d2,(a2)+            save it

        sub     d1,d2               any difference?

        beq.s   equ                 branch if not

        move    d0,d2

        lsl     #1,d2

        subi    #$2000,d2

        move    d2,d1

        asr     #4,d1

        sub     d1,d0

equ     move    (a2)+,d1

        add     d1,d2

        sub     (a2)+,d2

        asr     #8,d2

        sub     d2,d1

        move    d1,-4(a2)

        add     d1,d0

        move    d0,-8(a2)

        swap    d1


        add     (a2),d1             lowpass to remove the carrier

        asr     #1,d1

        move    d1,(a2)+            lp1

        add     (a2),d1

        asr     #1,d1

        move    d1,(a2)+            lp2

        

* Clock recovery DPLL & Carrier detect

        andi    #$8000,d1           limit sample stream

        move    (a2),d0             sign

        move    d1,(a2)+


        move.l  (a2),d2             bitclock and fraction

        cmp     d1,d0

        beq.s   L38


        move.l  d2,d0               cccc.pppp

        lsr.l   #3,d0               000c.cccp

        subi    #$9000,d0

        ext.l   d0

        sub.l   d0,d2


* Sampling / 8

L38     swap    d2                  clock in d2

        move    d2,d0

        addq    #1,d2               clock++

        swap    d2

        move.l  d2,(a2)+            update clock

        andi    #7,d0               

        beq.s   rdbit               sample data at 8 clockticks

        movem.l (a7)+,d0-d2/a0-a3

        rte


* Decode NRZI

rdbit   move    (a2),d0 search for transitions

        move    d1,(a2)+

        sub     d0,d1

        not     d1

        move.l  (a2),d0             get byte

        roxl    #1,d1               sign of d1 is bit

        roxl.l  #1,d0               shift it in

        move.l  d0,(a2)+            and save it


        move    (a2),d2             bitcount in d2 (init at -1)

        bpl.s   rxfram

        cmpi.l  #$1acffc1d,d0       start sequence in stream

        bne.s   irq9

        move    #2048,d2            256 bytes of 8 bits to go

        move.l  2(a2),a3            rxbuf ptr

        clr     (a3)                reset index

rxfram  move    d2,d1

        subq    #1,d2

        bpl.s   cont

        move    #-1,6(a2)           frame complete

cont    move    d2,(a2)+            update bitcount

        andi    #$1f,d1             write every 4 bytes

        bne.s   irq9

        move.l  (a2)+,a3            rxbuf ptr

        move    (a3)+,d1            index in rxbuf

        move.l  d0,(a3,d1.w)

        addq    #4,d1

        move    d1,-2(a3)

irq9    movem.l (a7)+,d0-d2/a0-a3

        rte

        

#endasm