source: software/firmware/main.c @ 7

Last change on this file since 7 was 1, checked in by bouyer, 8 years ago

Initial commit of soc-conso files

File size: 5.9 KB
Line 
1#include <pic18fregs.h>
2#include <stdio.h> 
3#include <math.h> 
4#include <my_serial.h> 
5
6extern char stack; 
7extern char stack_end;
8
9#pragma stack 0x100 256
10
11void _reset (void) __naked __interrupt 0;
12void _startup (void) __naked;
13
14static char counter_1hz;               
15static volatile short counter_10hz;           
16static volatile unsigned int softintrs;
17#define INT_10HZ         0x0001
18#define INT_AD           0x0002
19#define INT_DOAD         0x0004
20
21#define TIMER0_5MS 192 /* 48 without PLL */
22
23#define TIMER2_10HZ 1000
24
25#define CLRWDT __asm__("clrwdt")     
26#define SLEEP __asm__("sleep")     
27
28static char ad_channel;
29static long ad_i_result;
30static long ad_v_result;
31
32#define PRINTHEX(v) \
33        { \
34                unsigned char c = (v); \
35                if (c < 10) { \
36                        putchar('0' + c); \
37                } else { \
38                        putchar(('a' - 10) + c ); \
39                } \
40        }
41
42void
43main(void) __naked
44{
45        unsigned char c;
46        softintrs = 0;
47        counter_1hz = 10;
48
49        ANCON0 = 0xf0; /* an0-an3 analog, an4-an7 digital */
50        ANCON1 = 0x3f; /* an8-12 digital */
51
52        TRISCbits.TRISC1 = 0;
53        TRISCbits.TRISC2 = 0;
54        PORTCbits.RC1 = 0;
55        PORTCbits.RC2 = 0;
56
57
58        /* switch PLL on */
59        OSCTUNEbits.PLLEN = 1;
60
61        /* configure sleep mode: PRI_IDLE */
62        OSCCONbits.SCS = 0;
63        OSCCONbits.IDLEN = 1;
64        /* everything is low priority by default */
65        IPR1 = 0;
66        IPR2 = 0;
67        IPR3 = 0;
68        IPR4 = 0;
69        IPR5 = 0;
70        INTCON = 0;
71        INTCON2 = 0;
72        INTCON3 = 0;
73        INTCON2bits.RBPU = 1;
74
75        RCONbits.IPEN=1; /* enable interrupt priority */
76
77        /* configure timer0 as free-running counter at 46.875Khz */   
78        T0CON = 0x07; /* b00000111: internal clock, 1/256 prescaler */ 
79        INTCONbits.TMR0IF = 0;
80        INTCONbits.TMR0IE = 0; /* no interrupt */
81        T0CONbits.TMR0ON = 1;
82
83#if 0
84        /* configure UART for 57600Bps at 48Mhz */
85        SPBRG1 = 12;
86#endif
87        /* configure UART for 921600Bps at 48Mhz */
88        TXSTA1bits.BRGH = 1;
89        BAUDCON1bits.BRG16 = 1;
90        SPBRGH1 = 0;
91        SPBRG1 = 12;
92
93        USART_INIT(0);
94        stdout = STREAM_USER; /* Use the macro PUTCHAR with printf */
95
96#if TIMER2_10HZ == 100
97        /* configure timer2 for 1Khz interrupt */
98        T2CON = 0x22; /* b00100010: postscaller 1/5, prescaler 1/16 */
99        PR2 = 150; /* 1khz output */
100#elif TIMER2_10HZ == 1000
101        /* configure timer2 for 10Khz interrupt */
102        T2CON = 0x22; /* b00100010: postscaller 1/5, prescaler 1/16 */ 
103        PR2 = 15; /* 10khz output */
104#elif TIMER2_10HZ == 2000
105        /* configure timer2 for 20Khz interrupt */
106        T2CON = 0x21; /* b00100001: postscaller 1/5, prescaler 1/4 */ 
107        PR2 = 29; /* 20khz output */
108#else
109#error "unknown TIMER2_10HZ"
110#endif
111        counter_10hz = TIMER2_10HZ;
112        T2CONbits.TMR2ON = 1;
113        PIR1bits.TMR2IF = 0;
114        IPR1bits.TMR2IP = 1; /* high priority interrupt */
115        PIE1bits.TMR2IE = 1;
116
117
118        INTCONbits.GIE_GIEH=1;  /* enable high-priority interrupts */   
119        INTCONbits.PEIE_GIEL=1; /* enable low-priority interrrupts */   
120
121        /*
122         * configure ADC:
123         * AN3: vref+
124         * AN2: I
125         * AN1: vout
126         */
127
128        ADCON0 = 0xc1; /* b11000001 */
129        /* clk = fosc/64, tacq = 4tad (5.33us) */
130        ADCON1 = 0x96; /* b10010110 */
131        /* ANCON already set up */
132
133        /* start calibration */
134        ADCON1bits.ADCAL = 1;
135        ADCON0bits.GO_NOT_DONE =1;
136        while (ADCON0bits.GO_NOT_DONE)
137                ; /* wait */
138        ADCON1bits.ADCAL = 0;
139        PIR1bits.ADIF = 0;
140        PIE1bits.ADIE = 1;
141
142        printf("hello world\n");
143        /* enable watch dog timer */ 
144        WDTCON = 0x01;
145
146        printf("\nready\n");
147        /* start I calibration process */
148        ad_channel = 0;
149        ADCON0bits.CHS = 0;
150        softintrs &= ~INT_DOAD;
151        PORTCbits.RC1 = 1;
152        PORTCbits.RC2 = 0;
153
154again:
155        while (1) {
156                CLRWDT;
157                if (softintrs & INT_AD) {
158                        softintrs &= ~INT_AD;
159                        if (ad_channel == 0) {
160                                PRINTHEX(PORTB & 0xf);
161                                PRINTHEX(ADRESH & 0xf);
162                                PRINTHEX(ADRESL >> 4);
163                                PRINTHEX(ADRESL & 0xf);
164
165                                //printf("%1x%3x", (PORTB & 0xf), ADRESL | (ADRESH << 8));
166                                /*
167                                 * needs 2Tac, or 32 instrutions
168                                 * before next sample. assume we
169                                 * already have them since the
170                                 * interrupt
171                                 */
172                                ad_channel = 1;
173                                ADCON0bits.CHS = 1;
174                        } else {
175                                ad_channel = 0;
176                                ADCON0bits.CHS = 0;
177                                PRINTHEX(ADRESH & 0xf);
178                                PRINTHEX(ADRESL >> 4);
179                                PRINTHEX(ADRESL & 0xf);
180                                putchar('X');
181                                //printf("%3xX", ADRESL | (ADRESH << 8));
182                        }
183                }
184
185                if ((softintrs & INT_AD) == 0 &&
186                    (softintrs & INT_DOAD) && 
187                    ADCON0bits.GO_NOT_DONE == 0) {
188                        ADCON0bits.GO_NOT_DONE = 1;
189                        softintrs &= ~INT_DOAD;
190                }
191
192                if (RCREG1 == 'r')
193                        break;
194                SLEEP;
195
196        }
197
198end:
199
200        while ((c = getchar()) != 'r') {
201                printf("got %c\n", c);
202                goto again;
203        }
204        printf("returning\n");
205        while (PIE1bits.TX1IE)
206                ; /* wait for transmit to complete */
207        INTCONbits.PEIE=0; /* disable peripheral interrupts */
208        INTCONbits.GIE=0;  /* disable interrrupts */
209}
210
211unsigned int
212timer0_read() __naked   
213{
214        /* return TMR0L | (TMR0H << 8), reading TMR0L first */
215        __asm   
216        movf    _TMR0L, w
217        movff   _TMR0H, _PRODL
218        return
219        __endasm;       
220}
221
222/* Vectors */
223void _reset (void) __naked __interrupt 0
224{
225        __asm__("goto __startup");
226}
227
228
229void _startup (void) __naked
230{
231
232  __asm
233    // Initialize the stack pointer
234    lfsr 1, _stack_end
235    lfsr 2, _stack_end
236    clrf _TBLPTRU, 0    // 1st silicon doesn't do this on POR
237   
238    // initialize the flash memory access configuration. this is harmless
239    // for non-flash devices, so we do it on all parts.
240    bsf _EECON1, 7, 0
241    bcf _EECON1, 6, 0
242    __endasm ;
243
244  /* Call the user's main routine */
245  main();
246  __asm__("reset");
247}
248
249/*
250 * high priority interrupt. Split in 2 parts; one for the entry point
251 * where we'll deal with timer0, then jump to another address
252 * as we don't have enough space before the low priority vector
253 */
254void _irqh (void) __naked __shadowregs __interrupt 1
255{
256        __asm
257        bcf   _PIR1, 1
258        goto _irqh_timer2
259        __endasm ;
260
261}
262
263void irqh_timer2(void) __naked
264{
265        /*
266         * no sdcc registers are automatically saved,
267         * so we have to be carefull with C code !
268         */
269#if 0
270        counter_10hz--;
271        if (counter_10hz == 0) {
272                counter_10hz = TIMER2_10HZ;
273                softintrs |= INT_10HZ;
274        }                           
275#endif
276        if (softintrs & INT_DOAD) {
277                PORTCbits.RC2=1;
278        }
279        softintrs |= INT_DOAD;
280        __asm
281        retfie 1
282        nop
283        __endasm;
284}
285
286void _irq (void) __interrupt 2 /* low priority */
287{
288        USART_INTR;
289        if (PIE1bits.ADIE && PIR1bits.ADIF) {
290                PIR1bits.ADIF = 0;
291                softintrs |= INT_AD;
292        }
293}
Note: See TracBrowser for help on using the repository browser.