1 | #include <pic18fregs.h> |
---|
2 | #include <stdio.h> |
---|
3 | #include <math.h> |
---|
4 | #include <my_serial.h> |
---|
5 | #include <my_serial2.h> |
---|
6 | |
---|
7 | extern char stack; |
---|
8 | extern char stack_end; |
---|
9 | |
---|
10 | #pragma stack 0x100 256 |
---|
11 | |
---|
12 | void _reset (void) __naked __interrupt 0; |
---|
13 | void _startup (void) __naked; |
---|
14 | |
---|
15 | static char counter_1hz; |
---|
16 | static volatile short counter_10hz; |
---|
17 | static volatile unsigned char softintrs; |
---|
18 | #define INT_10HZ (unsigned char)0x01 |
---|
19 | #define INT_AD (unsigned char)0x02 |
---|
20 | #define INT_RX1 (unsigned char)0x08 |
---|
21 | #define INT_RX1OF (unsigned char)0x10 |
---|
22 | |
---|
23 | static volatile unsigned char status; |
---|
24 | #define STAT_WAIT (unsigned char)0x00 |
---|
25 | #define STAT_MEASURE (unsigned char)0x01 |
---|
26 | #define STAT_EXIT (unsigned char)0x02 |
---|
27 | #define STAT_CONSOLE (unsigned char)0x04 |
---|
28 | |
---|
29 | static volatile unsigned char adstatus; |
---|
30 | #define ADSTAT_MEASURE (unsigned char)0x01 |
---|
31 | static unsigned char ad_resh; |
---|
32 | static unsigned char ad_resl; |
---|
33 | static unsigned char ad_channel; |
---|
34 | |
---|
35 | |
---|
36 | #define TIMER0_5MS 192 /* 48 without PLL */ |
---|
37 | |
---|
38 | #define TIMER2_10HZ 1000 |
---|
39 | |
---|
40 | #define LEDR LATAbits.LATA7 |
---|
41 | #define LEDG LATAbits.LATA6 |
---|
42 | #define PWRON LATCbits.LATC2 |
---|
43 | #define RL1 LATCbits.LATC4 |
---|
44 | #define RL2 LATCbits.LATC5 |
---|
45 | #define SENSE PORTAbits.RA5 |
---|
46 | |
---|
47 | #define CLRWDT __asm__("clrwdt") |
---|
48 | #define SLEEP __asm__("sleep") |
---|
49 | |
---|
50 | static void do_measure(void); |
---|
51 | static void do_console(void); |
---|
52 | static void do_cal_data(void); |
---|
53 | static void parse_rx(void); |
---|
54 | |
---|
55 | static char buf[84]; |
---|
56 | |
---|
57 | /* address of calibration data in RAM */ |
---|
58 | #define cal_data 0x01F000 |
---|
59 | |
---|
60 | |
---|
61 | #if 1 |
---|
62 | #define PRINTHEX(v) \ |
---|
63 | { \ |
---|
64 | unsigned char c = (v); \ |
---|
65 | if (c < 10) { \ |
---|
66 | uart_putchar_hard('0' + c); \ |
---|
67 | } else { \ |
---|
68 | uart_putchar_hard(('a' - 10) + c ); \ |
---|
69 | } \ |
---|
70 | } |
---|
71 | #else |
---|
72 | #define PRINTHEX(v) {} |
---|
73 | #endif |
---|
74 | |
---|
75 | void |
---|
76 | main(void) __naked |
---|
77 | { |
---|
78 | softintrs = 0; |
---|
79 | counter_1hz = 10; |
---|
80 | |
---|
81 | ANCON0 = 0xf0; /* an0-an3 analog, an4-an7 digital */ |
---|
82 | ANCON1 = 0x3f; /* an8-12 digital */ |
---|
83 | |
---|
84 | RL1 = 0; |
---|
85 | TRISCbits.TRISC4 = 0; |
---|
86 | RL2 = 0; |
---|
87 | TRISCbits.TRISC5 = 0; |
---|
88 | PWRON = 0; |
---|
89 | TRISCbits.TRISC2 = 0; |
---|
90 | LEDR = 1; |
---|
91 | TRISAbits.TRISA7 = 0; |
---|
92 | LEDG = 0; |
---|
93 | TRISAbits.TRISA6 = 0; |
---|
94 | |
---|
95 | /* switch PLL on */ |
---|
96 | OSCTUNEbits.PLLEN = 1; |
---|
97 | |
---|
98 | /* configure sleep mode: PRI_IDLE */ |
---|
99 | OSCCONbits.SCS = 0; |
---|
100 | OSCCONbits.IDLEN = 1; |
---|
101 | /* everything is low priority by default */ |
---|
102 | IPR1 = 0; |
---|
103 | IPR2 = 0; |
---|
104 | IPR3 = 0; |
---|
105 | IPR4 = 0; |
---|
106 | IPR5 = 0; |
---|
107 | INTCON = 0; |
---|
108 | INTCON2 = 0; |
---|
109 | INTCON3 = 0; |
---|
110 | INTCON2bits.RBPU = 1; |
---|
111 | |
---|
112 | RCONbits.IPEN=1; /* enable interrupt priority */ |
---|
113 | |
---|
114 | /* configure timer0 as free-running counter at 46.875Khz */ |
---|
115 | T0CON = 0x07; /* b00000111: internal clock, 1/256 prescaler */ |
---|
116 | INTCONbits.TMR0IF = 0; |
---|
117 | INTCONbits.TMR0IE = 0; /* no interrupt */ |
---|
118 | T0CONbits.TMR0ON = 1; |
---|
119 | |
---|
120 | #if 0 |
---|
121 | /* configure UART for 57600Bps at 48Mhz */ |
---|
122 | SPBRG1 = 12; |
---|
123 | #endif |
---|
124 | /* configure UART for 921600Bps at 48Mhz */ |
---|
125 | TXSTA1bits.BRGH = 1; |
---|
126 | BAUDCON1bits.BRG16 = 1; |
---|
127 | SPBRGH1 = 0; |
---|
128 | SPBRG1 = 12; |
---|
129 | |
---|
130 | /* pre-configure UART2 */ |
---|
131 | /* turn off PPS write protect */ |
---|
132 | __asm |
---|
133 | banksel _PPSCON |
---|
134 | movlw 0x55 |
---|
135 | movwf _EECON2, a |
---|
136 | movlw 0xAA |
---|
137 | movwf _EECON2, a |
---|
138 | BCF _PPSCON, _IOLOCK, b |
---|
139 | __endasm; |
---|
140 | |
---|
141 | TRISCbits.TRISC0 = 1; |
---|
142 | LATCbits.LATC1 = 1; |
---|
143 | TRISCbits.TRISC1 = 0; |
---|
144 | RPINR16 = 11; /* RC0 = RX */ |
---|
145 | RPOR12 = 6; /* RC1 = TX */ |
---|
146 | TXSTA2 = 0x24; /* TXEN, BRGH set, others clear */ |
---|
147 | RCSTA2 = 0x90; /* UART enable, receiver disabled */ |
---|
148 | BAUDCON2 = 0x08; /* BRG16 */ |
---|
149 | |
---|
150 | USART_INIT(0); |
---|
151 | USART2_INIT(0); |
---|
152 | |
---|
153 | stdout = STREAM_USER; /* Use the macro PUTCHAR with printf */ |
---|
154 | |
---|
155 | #if TIMER2_10HZ == 100 |
---|
156 | /* configure timer2 for 1Khz interrupt */ |
---|
157 | T2CON = 0x22; /* b00100010: postscaller 1/5, prescaler 1/16 */ |
---|
158 | PR2 = 150; /* 1khz output */ |
---|
159 | #elif TIMER2_10HZ == 1000 |
---|
160 | /* configure timer2 for 10Khz interrupt */ |
---|
161 | T2CON = 0x22; /* b00100010: postscaller 1/5, prescaler 1/16 */ |
---|
162 | PR2 = 15; /* 10khz output */ |
---|
163 | #elif TIMER2_10HZ == 2000 |
---|
164 | /* configure timer2 for 20Khz interrupt */ |
---|
165 | T2CON = 0x21; /* b00100001: postscaller 1/5, prescaler 1/4 */ |
---|
166 | PR2 = 29; /* 20khz output */ |
---|
167 | #else |
---|
168 | #error "unknown TIMER2_10HZ" |
---|
169 | #endif |
---|
170 | counter_10hz = TIMER2_10HZ; |
---|
171 | T2CONbits.TMR2ON = 1; |
---|
172 | PIR1bits.TMR2IF = 0; |
---|
173 | IPR1bits.TMR2IP = 1; /* high priority interrupt */ |
---|
174 | PIE1bits.TMR2IE = 1; |
---|
175 | |
---|
176 | status = STAT_WAIT; |
---|
177 | adstatus = 0; |
---|
178 | |
---|
179 | INTCONbits.GIE_GIEH=1; /* enable high-priority interrupts */ |
---|
180 | INTCONbits.PEIE_GIEL=1; /* enable low-priority interrrupts */ |
---|
181 | |
---|
182 | /* |
---|
183 | * configure ADC: |
---|
184 | * AN3: vref+ |
---|
185 | * AN2: I |
---|
186 | * AN1: vout |
---|
187 | */ |
---|
188 | |
---|
189 | ADCON0 = 0xc1; /* b11000001 */ |
---|
190 | /* clk = fosc/64, tacq = 4tad (5.33us) */ |
---|
191 | ADCON1 = 0x96; /* b10010110 */ |
---|
192 | /* ANCON already set up */ |
---|
193 | |
---|
194 | /* start calibration */ |
---|
195 | ADCON1bits.ADCAL = 1; |
---|
196 | ADCON0bits.GO_NOT_DONE =1; |
---|
197 | while (ADCON0bits.GO_NOT_DONE) |
---|
198 | ; /* wait */ |
---|
199 | ADCON1bits.ADCAL = 0; |
---|
200 | PIR1bits.ADIF = 0; |
---|
201 | PIE1bits.ADIE = 1; |
---|
202 | |
---|
203 | printf("hello world\n"); |
---|
204 | /* enable watch dog timer */ |
---|
205 | WDTCON = 0x01; |
---|
206 | LEDR = 0; |
---|
207 | |
---|
208 | printf("\nready\n"); |
---|
209 | ad_channel = 0; |
---|
210 | ADCON0bits.CHS = 0; |
---|
211 | LEDG = 1; |
---|
212 | PWRON = 0; |
---|
213 | |
---|
214 | while ((status & STAT_EXIT) == 0) { |
---|
215 | CLRWDT; |
---|
216 | if (softintrs & INT_10HZ) { |
---|
217 | softintrs &= ~INT_10HZ; |
---|
218 | LEDG ^= 1; |
---|
219 | } |
---|
220 | if (softintrs & INT_RX1) { |
---|
221 | parse_rx(); |
---|
222 | } else { |
---|
223 | SLEEP; |
---|
224 | continue; |
---|
225 | } |
---|
226 | if (status & STAT_MEASURE) |
---|
227 | do_measure(); |
---|
228 | else if (status & STAT_CONSOLE) |
---|
229 | do_console(); |
---|
230 | } |
---|
231 | printf("returning\n"); |
---|
232 | while (PIE1bits.TX1IE) |
---|
233 | ; /* wait for transmit to complete */ |
---|
234 | INTCONbits.PEIE=0; /* disable peripheral interrupts */ |
---|
235 | INTCONbits.GIE=0; /* disable interrrupts */ |
---|
236 | } |
---|
237 | |
---|
238 | static void |
---|
239 | parse_rx() |
---|
240 | { |
---|
241 | char c; |
---|
242 | char c2; |
---|
243 | char ok = 1; |
---|
244 | char err = 0; |
---|
245 | long br; |
---|
246 | short brgreg = 0; |
---|
247 | |
---|
248 | softintrs &= ~INT_RX1; |
---|
249 | c = uart_getchar(); |
---|
250 | switch(c) { |
---|
251 | case 'B': |
---|
252 | c = uart_getchar(); |
---|
253 | br = 0; |
---|
254 | while(c != '\n') { |
---|
255 | if (c < '0' || c > '9') { |
---|
256 | err = 1; |
---|
257 | break; |
---|
258 | } |
---|
259 | br = br * 10 + c - '0'; |
---|
260 | c = uart_getchar(); |
---|
261 | } |
---|
262 | if (br > 0) { |
---|
263 | /* |
---|
264 | * brg = F / 16 / (n + 1) |
---|
265 | * brg * (n + 1) = F / 16 |
---|
266 | * n + 1 = F / 16 / brg |
---|
267 | * n = F / 16 / brg - 1 |
---|
268 | * with F = 48Mhz |
---|
269 | * n = 3000000 / brg - 1 |
---|
270 | */ |
---|
271 | brgreg = (12000000L + br / 2) / br - 1; |
---|
272 | printf("brgreg %d\n", brgreg); |
---|
273 | } |
---|
274 | if (err == 0) { |
---|
275 | if (br > 0) { |
---|
276 | SPBRGH2 = (brgreg >> 8); |
---|
277 | SPBRG2 = (brgreg & 0xff); |
---|
278 | } |
---|
279 | status = STAT_CONSOLE; |
---|
280 | } |
---|
281 | break; |
---|
282 | case 'C': |
---|
283 | do_cal_data(); |
---|
284 | c = '\n'; |
---|
285 | break; |
---|
286 | case 'E': |
---|
287 | status = STAT_EXIT; |
---|
288 | break; |
---|
289 | case 'M': |
---|
290 | c = uart_getchar(); |
---|
291 | if (c == '0') { |
---|
292 | if (status == STAT_MEASURE) |
---|
293 | ok = 0; |
---|
294 | status = STAT_WAIT; |
---|
295 | } else if (c == '1') { |
---|
296 | status = STAT_MEASURE; |
---|
297 | } else { |
---|
298 | err = 1; |
---|
299 | } |
---|
300 | break; |
---|
301 | case 'P': |
---|
302 | c = uart_getchar(); |
---|
303 | if (c == '0') |
---|
304 | PWRON = 0; |
---|
305 | else if (c == '1') |
---|
306 | PWRON = 1; |
---|
307 | else |
---|
308 | err = 1; |
---|
309 | break; |
---|
310 | case 'R': |
---|
311 | c = uart_getchar(); |
---|
312 | if (c != '\n') { |
---|
313 | c2 = uart_getchar(); |
---|
314 | if (c == '1') { |
---|
315 | if (c2 == '0') |
---|
316 | RL1 = 0; |
---|
317 | else if (c2 == '1') |
---|
318 | RL1 = 1; |
---|
319 | else |
---|
320 | err = 1; |
---|
321 | } else if (c == '2') { |
---|
322 | if (c2 == '0') |
---|
323 | RL2 = 0; |
---|
324 | else if (c2 == '1') |
---|
325 | RL2 = 1; |
---|
326 | else |
---|
327 | err = 1; |
---|
328 | } else { |
---|
329 | err = 1; |
---|
330 | } |
---|
331 | c = c2; |
---|
332 | } |
---|
333 | break; |
---|
334 | case 'S': |
---|
335 | printf("power %s RL %s %s SENSE %s GPIO 0x%x\n", |
---|
336 | PWRON ? "on" : "off", |
---|
337 | RL1 ? "on" : "off", |
---|
338 | RL2 ? "on" : "off", |
---|
339 | SENSE ? "off" : "on", |
---|
340 | PORTB); |
---|
341 | break; |
---|
342 | default: |
---|
343 | err = 1; |
---|
344 | break; |
---|
345 | } |
---|
346 | while (c != '\n') |
---|
347 | c = uart_getchar(); |
---|
348 | if (err) |
---|
349 | printf("\nERROR\n"); |
---|
350 | else if (ok) |
---|
351 | printf("\nOK\n"); |
---|
352 | |
---|
353 | if (softintrs & INT_RX1OF) { |
---|
354 | PIE1bits.RC1IE = 0; |
---|
355 | softintrs &= ~INT_RX1OF; |
---|
356 | softintrs &= ~INT_RX1; |
---|
357 | uart_rxbuf_prod = uart_rxbuf_cons = 0; |
---|
358 | PIE1bits.RC1IE = 1; |
---|
359 | } |
---|
360 | } |
---|
361 | |
---|
362 | static void |
---|
363 | printhex(unsigned char c) __wparam __naked |
---|
364 | { |
---|
365 | (void)c; |
---|
366 | __asm |
---|
367 | andlw 0x0f; |
---|
368 | sublw 9; |
---|
369 | bc decimal; |
---|
370 | sublw '@'; |
---|
371 | goto _uart_putchar_hard; |
---|
372 | decimal: |
---|
373 | sublw '9'; |
---|
374 | goto _uart_putchar_hard; |
---|
375 | __endasm; |
---|
376 | } |
---|
377 | |
---|
378 | static void |
---|
379 | do_measure() |
---|
380 | { |
---|
381 | softintrs &= ~INT_AD; |
---|
382 | adstatus = ADSTAT_MEASURE; |
---|
383 | ADCON0bits.CHS = 0; |
---|
384 | |
---|
385 | LEDR = 0; |
---|
386 | LEDG = 1; |
---|
387 | UART_FLUSH(); |
---|
388 | uart_putchar_hard('X'); |
---|
389 | while (status & STAT_MEASURE) { |
---|
390 | CLRWDT; |
---|
391 | if (softintrs & INT_AD) { |
---|
392 | if (ad_channel == 0) { |
---|
393 | printhex(PORTB >> 4); |
---|
394 | printhex(PORTB); |
---|
395 | printhex(ad_resh); |
---|
396 | printhex(ad_resl >> 4); |
---|
397 | printhex(ad_resl); |
---|
398 | } else { |
---|
399 | printhex(ad_resh); |
---|
400 | printhex(ad_resl >> 4); |
---|
401 | printhex(ad_resl); |
---|
402 | uart_putchar_hard('X'); |
---|
403 | } |
---|
404 | softintrs &= ~INT_AD; |
---|
405 | } |
---|
406 | if (softintrs & INT_RX1) { |
---|
407 | parse_rx(); |
---|
408 | } else { |
---|
409 | SLEEP; |
---|
410 | } |
---|
411 | } |
---|
412 | adstatus = 0; |
---|
413 | printf("\nOK\n"); |
---|
414 | } |
---|
415 | |
---|
416 | static void |
---|
417 | do_console() |
---|
418 | { |
---|
419 | char previous_rx1 = 0; |
---|
420 | char c; |
---|
421 | char more_work = 0; |
---|
422 | |
---|
423 | printf("connecting to console - exit with #.\n"); |
---|
424 | /* clear buffer */ |
---|
425 | PIE3bits.RC2IE = 0; |
---|
426 | uart2_rxbuf_prod = uart2_rxbuf_cons = 0; |
---|
427 | PIE3bits.RC2IE = 1; |
---|
428 | RCSTA2bits.SPEN = 1; |
---|
429 | while ((status & STAT_CONSOLE) || more_work) { |
---|
430 | CLRWDT; |
---|
431 | more_work = 0; |
---|
432 | if (softintrs & INT_10HZ) { |
---|
433 | softintrs &= ~INT_10HZ; |
---|
434 | LEDG ^= 1; |
---|
435 | } |
---|
436 | if (uart_rxbuf_cons != uart_rxbuf_prod) { |
---|
437 | c = uart_getchar(); |
---|
438 | /* |
---|
439 | * #. exits console mode |
---|
440 | * ## sends # |
---|
441 | * anything else send both char unmodified |
---|
442 | */ |
---|
443 | if (previous_rx1 == '#') { |
---|
444 | if (c == '.') { |
---|
445 | status = STAT_WAIT; |
---|
446 | } else if (c == '#') { |
---|
447 | uart2_putchar_raw(c); |
---|
448 | } else { |
---|
449 | uart2_putchar_raw(previous_rx1); |
---|
450 | uart2_putchar_raw(c); |
---|
451 | } |
---|
452 | } else { |
---|
453 | uart2_putchar_raw(c); |
---|
454 | } |
---|
455 | previous_rx1 = c; |
---|
456 | more_work = 1; |
---|
457 | } |
---|
458 | if (uart2_rxbuf_cons != uart2_rxbuf_prod) { |
---|
459 | c = uart2_getchar(); |
---|
460 | uart_putchar_raw(c); |
---|
461 | more_work = 1; |
---|
462 | } |
---|
463 | if (more_work == 0 && (status & STAT_CONSOLE)) |
---|
464 | SLEEP; |
---|
465 | } |
---|
466 | RCSTA2bits.SPEN = 0; |
---|
467 | printf("exit from console\n"); |
---|
468 | } |
---|
469 | |
---|
470 | static void |
---|
471 | do_write(void) |
---|
472 | { |
---|
473 | EECON2 = 0x55; |
---|
474 | EECON2 = 0xaa; |
---|
475 | EECON1bits.WR = 1; |
---|
476 | while (EECON1bits.WR) |
---|
477 | ; /* wait */ |
---|
478 | } |
---|
479 | |
---|
480 | static void |
---|
481 | do_cal_data() |
---|
482 | { |
---|
483 | char i = 0; |
---|
484 | char err = 0; |
---|
485 | char c; |
---|
486 | |
---|
487 | c = uart_getchar(); |
---|
488 | while (c != '\n') { |
---|
489 | if ((c < '0' || c > '9') && c != ' ' && c != '.') { |
---|
490 | printf("cal error at %c (%d)\n", c, i); |
---|
491 | err = 1; |
---|
492 | } |
---|
493 | if (i > 82) { |
---|
494 | printf("cal error at %c (%d)\n", c, i); |
---|
495 | err = 1; |
---|
496 | } else { |
---|
497 | buf[i] = c; |
---|
498 | i++; |
---|
499 | } |
---|
500 | c = uart_getchar(); |
---|
501 | } |
---|
502 | if (err == 0 && i != 0 && i != 83) { |
---|
503 | printf("cal error: %d\n", i); |
---|
504 | } else if (err == 0 && i != 0) { |
---|
505 | /* erase 1k block */ |
---|
506 | INTCONbits.GIE_GIEH=0; /* disable interrupts */ |
---|
507 | INTCONbits.PEIE_GIEL=0; |
---|
508 | TBLPTRU = ((long)cal_data >> 16) & 0xff; |
---|
509 | TBLPTRH = ((long)cal_data >> 8) & 0xff; |
---|
510 | TBLPTRL = (long)cal_data & 0xff; |
---|
511 | EECON1 = 0x14; /* enable write+erase */ |
---|
512 | do_write(); |
---|
513 | EECON1 = 0x00; /* disable write */ |
---|
514 | for (i = 0; i < 83; i++) { |
---|
515 | TABLAT = buf[i]; |
---|
516 | __asm__("tblwt*+"); |
---|
517 | if (i == 63) { |
---|
518 | __asm__("tblrd*-"); |
---|
519 | EECON1 = 0x04; /* enable write */ |
---|
520 | do_write(); |
---|
521 | EECON1 = 0x00; /* disable write */ |
---|
522 | __asm__("tblrd*+"); |
---|
523 | } |
---|
524 | } |
---|
525 | __asm__("tblrd*-"); |
---|
526 | EECON1 = 0x04; /* enable write */ |
---|
527 | do_write(); |
---|
528 | EECON1 = 0x00; /* disable write */ |
---|
529 | INTCONbits.PEIE_GIEL=1; |
---|
530 | INTCONbits.GIE_GIEH=1; /* enable interrupts */ |
---|
531 | } |
---|
532 | printf("cal_data "); |
---|
533 | TBLPTRU = ((long)cal_data >> 16) & 0xff; |
---|
534 | TBLPTRH = ((long)cal_data >> 8) & 0xff; |
---|
535 | TBLPTRL = (long)cal_data & 0xff; |
---|
536 | EECON1 = 0x00; /* disable writes */ |
---|
537 | for (i = 0; i < 83; i++) { |
---|
538 | __asm__("tblrd*+"); |
---|
539 | putchar(TABLAT); |
---|
540 | } |
---|
541 | printf("\n"); |
---|
542 | } |
---|
543 | |
---|
544 | unsigned short |
---|
545 | timer0_read() __naked |
---|
546 | { |
---|
547 | /* return TMR0L | (TMR0H << 8), reading TMR0L first */ |
---|
548 | __asm |
---|
549 | movf _TMR0L, w |
---|
550 | movff _TMR0H, _PRODL |
---|
551 | return |
---|
552 | __endasm; |
---|
553 | } |
---|
554 | |
---|
555 | /* Vectors */ |
---|
556 | void _reset (void) __naked __interrupt 0 |
---|
557 | { |
---|
558 | __asm__("goto __startup"); |
---|
559 | } |
---|
560 | |
---|
561 | |
---|
562 | void _startup (void) __naked |
---|
563 | { |
---|
564 | |
---|
565 | __asm |
---|
566 | // Initialize the stack pointer |
---|
567 | lfsr 1, _stack_end |
---|
568 | lfsr 2, _stack_end |
---|
569 | clrf _TBLPTRU, 0 // 1st silicon doesn't do this on POR |
---|
570 | |
---|
571 | // initialize the flash memory access configuration. this is harmless |
---|
572 | // for non-flash devices, so we do it on all parts. |
---|
573 | bsf _EECON1, 7, 0 |
---|
574 | bcf _EECON1, 6, 0 |
---|
575 | __endasm ; |
---|
576 | |
---|
577 | /* Call the user's main routine */ |
---|
578 | main(); |
---|
579 | __asm__("reset"); |
---|
580 | } |
---|
581 | |
---|
582 | /* |
---|
583 | * high priority interrupt. Split in 2 parts; one for the entry point |
---|
584 | * where we'll deal with timer0, then jump to another address |
---|
585 | * as we don't have enough space before the low priority vector |
---|
586 | */ |
---|
587 | void _irqh (void) __naked __shadowregs __interrupt 1 |
---|
588 | { |
---|
589 | __asm |
---|
590 | bcf _PIR1, 1 |
---|
591 | goto _irqh_timer2 |
---|
592 | __endasm ; |
---|
593 | |
---|
594 | } |
---|
595 | |
---|
596 | void irqh_timer2(void) __naked |
---|
597 | { |
---|
598 | /* |
---|
599 | * no sdcc registers are automatically saved, |
---|
600 | * so we have to be carefull with C code ! |
---|
601 | */ |
---|
602 | counter_10hz--; |
---|
603 | if (counter_10hz == 0) { |
---|
604 | counter_10hz = TIMER2_10HZ; |
---|
605 | softintrs |= INT_10HZ; |
---|
606 | } |
---|
607 | if (adstatus & ADSTAT_MEASURE) { |
---|
608 | if (PIR1bits.ADIF) { |
---|
609 | LEDR = 1; |
---|
610 | } |
---|
611 | ADCON0bits.GO_NOT_DONE = 1; |
---|
612 | } |
---|
613 | __asm |
---|
614 | retfie 1 |
---|
615 | nop |
---|
616 | __endasm; |
---|
617 | } |
---|
618 | |
---|
619 | void _irq (void) __interrupt 2 /* low priority */ |
---|
620 | { |
---|
621 | USART_INTR; |
---|
622 | USART2_INTR; |
---|
623 | if (PIE1bits.ADIE && PIR1bits.ADIF) { |
---|
624 | if (softintrs & INT_AD) { |
---|
625 | LEDR = 1; |
---|
626 | } |
---|
627 | ad_channel = ADCON0bits.CHS; |
---|
628 | ad_resl = ADRESL; |
---|
629 | ad_resh = ADRESH; |
---|
630 | /* |
---|
631 | * needs 2Tac, or 32 instrutions |
---|
632 | * before next sample. assume we'll |
---|
633 | * have them at timer2 interrupt |
---|
634 | */ |
---|
635 | if (ad_channel == 0) |
---|
636 | ADCON0bits.CHS = 1; |
---|
637 | else |
---|
638 | ADCON0bits.CHS = 0; |
---|
639 | PIR1bits.ADIF = 0; |
---|
640 | softintrs |= INT_AD; |
---|
641 | } |
---|
642 | } |
---|