1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
void ADC(void) __attribute__ ((interrupt_handler,section(".icode")));
void ADC(void)
{
    static unsigned char channel IBSS_ATTR;
    /* read current value */
    adc_data[(channel & 0x03)] = ADVALUE;

    /* switch channel
     *
     * set source remark
     * ADCONFIG is 16bit wide so we have to shift data by 16bits left
     * thats why we shift <<24 instead of <<8
     */

    channel++;

    and_l(~(3<<24),&ADCONFIG);
    or_l( (((channel & 0x03) << 8 )|(1<<7))<<16, &ADCONFIG);

    if ( (channel & 0x03) == 0 )
        /* disable interrupt */
        and_l((~(1<<6))<<16,&ADCONFIG);
}

unsigned short adc_scan(int channel)
{
    /* maybe we can drop &0x03 part */
    return adc_data[(channel&0x03)];
}

void adc_start(void)
{
    /* enable adc interrupt */
    or_l( ((1<<6))<<16, &ADCONFIG);
}

void adc_init(void)
{
    /* GPIO38 GPIO39 */
    and_l(~((1<<6)|(1<<7)), &GPIO1_FUNCTION);

    /* ADOUT_SEL = 01
     * SOURCE SELECT = 000
     * CLEAR INTERRUPT FLAG
     * ENABLE INTERRUPT = 1
     * ADOUT_DRIVE = 00
     * ADCLK_SEL = 011 (busclk/2)
     */

    ADCONFIG = (1<<10)|(1<<7)|(1<<6)|(1<<1)|(1<<0);

    /* ADC interrupt level 4.0 */
    or_l((4<<28), &INTPRI8);

    tick_add_task(adc_start);
}