/[projet1]/public/oric/hardware/cumulus/boot/main.c
Defence Force logotype

Contents of /public/oric/hardware/cumulus/boot/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 484 - (show annotations)
Sat May 7 15:16:42 2011 UTC (8 years, 10 months ago) by retromaster
File MIME type: text/plain
File size: 19511 byte(s)
Fixed a critical bug in the UI code that causes problems with WD1793 emulation timings.
Reduced bootloader size by making font support optional.
Added pcb directory with gerber and drill files, and Bills of Materials.
Updated README.
1 /* Cumulus 18F46K20 Firmware
2 * SD Card Bootloader.
3 * Copyright 2010 Retromaster.
4 *
5 * This file is part of Cumulus Firmware.
6 *
7 * Cumulus Firmware is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License,
10 * or any later version.
11 *
12 * Cumulus Firmware is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Cumulus Firmware. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "p18f46K20.h"
22 #include "delays.h"
23
24 #ifdef TEXT_SUPPORT
25 #define NOFONT8X16
26 #include "fonts.h"
27 #endif
28
29 /* Config */
30 #pragma config FOSC = ECIO6
31 #pragma config FCMEN = OFF
32 #pragma config IESO = OFF
33 #pragma config PWRT = ON
34 #pragma config BOREN = OFF
35 #pragma config MCLRE = ON
36 #pragma config WDTEN = OFF
37 #pragma config LPT1OSC = OFF
38 #pragma config PBADEN = OFF
39 #pragma config STVREN = ON
40 #pragma config LVP = OFF
41 #pragma config XINST = OFF
42 #pragma config DEBUG = OFF
43 #pragma config CP0 = OFF
44 #pragma config CP1 = OFF
45 #pragma config CP2 = OFF
46 #pragma config CP3 = OFF
47 #pragma config CPB = OFF
48 #pragma config CPD = OFF
49 #pragma config WRT0 = OFF
50 #pragma config WRT1 = OFF
51 #pragma config WRT2 = OFF
52 #pragma config WRT3 = OFF
53 #pragma config WRTB = OFF
54 #pragma config WRTC = OFF
55 #pragma config WRTD = OFF
56
57 typedef signed char int8_t;
58 typedef unsigned char uint8_t;
59 typedef unsigned short uint16_t;
60 typedef unsigned long uint32_t;
61 typedef long int32_t;
62
63 #pragma udata
64 uint32_t fpp_begin_lba;
65 uint32_t fat_begin_lba;
66 uint32_t sectors_per_fat;
67 uint32_t cluster_begin_lba;
68 uint8_t sectors_per_cluster;
69 uint8_t fat_count;
70 uint16_t root_dir_first_cluster;
71 uint16_t reserved_sector_count;
72
73 #pragma udata sector_buffer_section
74 uint8_t sector_buffer[512];
75
76 #define RM_RESET_VECTOR 0x001000
77 #define RM_HIGH_INTERRUPT_VECTOR 0x001008
78 #define RM_LOW_INTERRUPT_VECTOR 0x001018
79
80 /* Vector remapping */
81 #pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
82 void _high_ISR (void)
83 {
84 _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm
85 }
86
87 #pragma code _LOW_INTERRUPT_VECTOR = 0x000018
88 void _low_ISR (void)
89 {
90 _asm goto RM_LOW_INTERRUPT_VECTOR _endasm
91 }
92
93 #pragma code
94 far rom char str_cumulus_bin[] = "CUMULUS BIN";
95
96 uint8_t erase_program_verify_page(uint16_t address, uint8_t* buf)
97 {
98 uint8_t i;
99 far rom uint8_t* rom_ptr;
100 rom_ptr = (far rom uint8_t*) address;
101
102 /* Dummy read, required for loading the table pointer */
103 i = *rom_ptr;
104
105 /* Erase */
106 EECON1bits.EEPGD = 1;
107 EECON1bits.CFGS = 0;
108 EECON1bits.FREE = 1;
109 EECON1bits.WREN = 1;
110 INTCONbits.GIE = 0;
111 EECON2 = 0x55;
112 EECON2 = 0xAA;
113 EECON1bits.WR = 1;
114 INTCONbits.GIE = 1;
115
116 /* Write 64 bytes */
117 for (i = 0; i < 64; i++)
118 rom_ptr[i] = buf[i];
119
120 EECON1bits.EEPGD = 1;
121 EECON1bits.CFGS = 0;
122 EECON1bits.FREE = 0;
123 EECON1bits.WREN = 1;
124 INTCONbits.GIE = 0;
125 EECON2 = 0x55;
126 EECON2 = 0xAA;
127 EECON1bits.WR = 1;
128 INTCONbits.GIE = 1;
129 EECON1bits.WREN = 0;
130
131 /* Verify 64 bytes */
132 for (i = 0; i < 64; i++)
133 if (rom_ptr[i] != buf[i])
134 return 0;
135
136 return 1;
137 }
138
139 #define PCF8833
140 //#define S1D15G10
141
142 #ifdef PCF8833
143
144 /* LCD Controller Commands */
145 #define SLEEPOUT 0x88 /* sleep out */
146 #define INVON 0x84 /* inversion ON */
147 #define SETCON 0xA4 /* write contrast */
148 #define DISPON 0x94 /* display ON */
149 #define CASET 0x54 /* column address set */
150 #define PASET 0xD4 /* page address set */
151 #define RAMWR 0x34 /* memory write */
152 #define MADCTL 0x6C /* memory access control */
153 #define COLMOD 0x5C /* interface pixel format */
154
155 #endif
156
157 #ifdef S1D15G10
158
159 #define DISON 0xF5 // Display on
160 #define DISINV 0xE5 // Inverse display
161 #define COMSCN 0xDD // Common scan direction
162 #define DISCTL 0x53 // Display control
163 #define SLPOUT 0x29 // Sleep out
164 //#define PASET 0xAE // Page address set
165 #define PASET 0xA8 // Page address set
166 //#define CASET 0xA8 // Column address set
167 #define CASET 0xAE // Column address set
168 #define DATCTL 0x3D // Data scan direction, etc.
169 #define RAMWR 0x3A // Writing to memory
170 #define OSCON 0x8B // Internal oscillation on
171 #define PWRCTR 0x04 // Power control
172 #define VOLCTR 0x81 // Electronic volume control
173
174 #endif
175
176 #if defined(PCF8833) || defined(S1D15G10)
177
178 /* Initialize EUSART module used for 9-bit SPI transmission. */
179 static void init_EUSART(void)
180 {
181 /* Set baud rate */
182 BAUDCONbits.CKTXP = 1;
183 BAUDCONbits.BRG16 = 0;
184 SPBRGH = 0;
185 SPBRG = 1;
186
187 /* Set TRIS bits */
188 TRISCbits.TRISC6 = 1;
189 TRISCbits.TRISC7 = 1;
190
191 /* Synchronous Master mode */
192 TXSTAbits.SYNC = 1;
193 TXSTAbits.CSRC = 1;
194 RCSTAbits.SPEN = 1;
195
196 /* Receive disabled, transmit enabled */
197 RCSTAbits.SREN = 0;
198 RCSTAbits.CREN = 0;
199 TXSTAbits.TXEN = 1;
200
201 /* 9-bit transmission */
202 TXSTAbits.TX9 = 1;
203 }
204
205 /* Write given command byte to LCD */
206 static void n6610_write_command(uint8_t command)
207 {
208 uint8_t value;
209
210 /* Move highest bit into TX9D */
211 if (command & 0x80)
212 TXSTAbits.TX9D = 1;
213 else
214 TXSTAbits.TX9D = 0;
215
216 /* Command byte */
217 value = (command << 1);
218
219 /* Wait until EUSART transmitter is free */
220 while (!TXSTAbits.TRMT);
221 TXREG = value;
222 }
223
224 /* Write given data byte to LCD */
225 static void n6610_write_data(uint8_t data)
226 {
227 uint8_t value;
228
229 /* Move highest bit into TX9D */
230 if (data & 0x80)
231 TXSTAbits.TX9D = 1;
232 else
233 TXSTAbits.TX9D = 0;
234
235 /* Data byte */
236 value = (data << 1) | 1;
237
238 /* Wait until EUSART transmitter is free */
239 while (!TXSTAbits.TRMT);
240 TXREG = value;
241 }
242
243 static const rom uint8_t reverse_table[16] = {
244 0b0000,
245 0b1000,
246 0b0100,
247 0b1100,
248 0b0010,
249 0b1010,
250 0b0110,
251 0b1110,
252 0b0001,
253 0b1001,
254 0b0101,
255 0b1101,
256 0b0011,
257 0b1011,
258 0b0111,
259 0b1111
260 };
261
262 static uint8_t reverse_bits(uint8_t value)
263 {
264 uint8_t rev;
265
266 rev = reverse_table[value & 0x0F] << 4;
267 rev |= reverse_table[(value & 0xF0) >> 4];
268
269 return rev;
270 }
271
272 /* Draws given area with given color. Area width must be multiple of 2. */
273 static void n6610_fill_area(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t v1, uint8_t v2, uint8_t v3)
274 {
275 uint8_t i, j;
276
277 x = (x & 0xFE);
278 w = (w & 0xFE);
279
280 /* Page address set */
281 n6610_write_command(CASET);
282 n6610_write_data(reverse_bits(x));
283 n6610_write_data(reverse_bits(x + w - 1));
284
285 /* Column address set */
286 n6610_write_command(PASET);
287 n6610_write_data(reverse_bits(y));
288 n6610_write_data(reverse_bits(y + h - 1));
289
290 /* Fill memory */
291 n6610_write_command(RAMWR);
292
293 for (i = 0; i < w / 2; i ++)
294 for (j = 0; j < h; j ++)
295 {
296 n6610_write_data(v1);
297 n6610_write_data(v2);
298 n6610_write_data(v3);
299 }
300 }
301
302 #ifdef TEXT_SUPPORT
303 /* Draws given character in b/w using the 6x8 Font. */
304 void n6610_draw_char(uint8_t x, uint8_t y, char c)
305 {
306 uint8_t i, j, v;
307 rom unsigned char* char_base;
308
309 c -= 31;
310
311 x = (x & 0xFE) | 0x01;
312
313 /* Page address set */
314 n6610_write_command(CASET);
315 n6610_write_data(reverse_bits(x + 1));
316 n6610_write_data(reverse_bits(x + 6));
317
318 /* Column address set */
319 n6610_write_command(PASET);
320 n6610_write_data(reverse_bits(y));
321 n6610_write_data(reverse_bits(y + 7));
322
323 /* Fill memory */
324 n6610_write_command(RAMWR);
325
326 char_base = (rom unsigned char*) _FONT6X8 + ((uint16_t) c) * 8;
327 for (i = 0; i < 8; i ++)
328 {
329 v = char_base[i];
330
331 for (j = 0; j < 6 / 2; j ++)
332 {
333 switch (v & 0xC0)
334 {
335 case 0x00:
336 n6610_write_data(0x00);
337 n6610_write_data(0x00);
338 n6610_write_data(0x00);
339 break;
340 case 0x40:
341 n6610_write_data(0x00);
342 n6610_write_data(0xF0);
343 n6610_write_data(0xFF);
344 break;
345 case 0x80:
346 n6610_write_data(0xFF);
347 n6610_write_data(0x0F);
348 n6610_write_data(0x00);
349 break;
350 case 0xC0:
351 n6610_write_data(0xFF);
352 n6610_write_data(0xFF);
353 n6610_write_data(0xFF);
354 break;
355 }
356
357 v = v << 2;
358 }
359 }
360 }
361
362 /* Draws given string in b/w using the 6x8 font */
363 void n6610_draw_rom_str(uint8_t x, uint8_t y, const far rom char* c)
364 {
365 while (*c)
366 {
367 n6610_draw_char(x, y, *c);
368 c ++;
369 x += 6;
370 }
371 }
372
373 #pragma romdata
374 rom char hex_lookup[16] =
375 {
376 '0', '1', '2', '3',
377 '4', '5', '6', '7',
378 '8', '9', 'A', 'B',
379 'C', 'D', 'E', 'F'
380 };
381
382 #pragma code
383 void n6610_debug_message_short(uint8_t y, const far rom char* msg, uint16_t val)
384 {
385 uint8_t start;
386 int8_t j;
387
388 // Draw string.
389 n6610_draw_rom_str(0, y, msg);
390
391 /* Print out value in hex */
392 for (j = 0; j < 4; j ++)
393 {
394 n6610_draw_char(120 - j * 6, y, hex_lookup[val & 0xF]);
395 val = val >> 4;
396 }
397 }
398 #endif
399 #endif
400
401 #ifdef PCF8833
402 /* Initialize LCD controller */
403 void n6610_init(void)
404 {
405 /* Initialize EUSART module for 9-bit synchronous transmission */
406 init_EUSART();
407
408 /* Setup RST and CS pins */
409 TRISCbits.TRISC0 = 0;
410 TRISCbits.TRISC1 = 0;
411
412 /* Reset */
413 PORTCbits.RC1 = 0;
414 Delay1KTCYx(1000);
415 PORTCbits.RC1 = 1;
416 Delay1KTCYx(1000);
417
418 /* Chip Select */
419 PORTCbits.RC0 = 0;
420
421 /* Sleep out (command 0x11) */
422 n6610_write_command(SLEEPOUT);
423
424 /* Color Interface Pixel Format (command 0x3A) */
425 n6610_write_command(COLMOD);
426 n6610_write_data(0xC0); /* 0x03 = 12 bits-per-pixel */
427
428 /* Memory access controller (command 0x36). */
429 n6610_write_command(MADCTL);
430 n6610_write_data(0x06); /* 0xE0 = mirror y, vertical, reverse rgb */
431
432 /* Write contrast (command 0x25) */
433 n6610_write_command(SETCON);
434 n6610_write_data(0x22); /* contrast 0x40 */
435 Delay1KTCYx(2);
436
437 /* Display On (command 0x29) */
438 n6610_write_command(DISPON);
439 }
440 #endif
441
442 #ifdef S1D15G10
443 /* Initialize LCD controller */
444 void n6610_init(void)
445 {
446 /* Initialize EUSART module for 9-bit synchronous transmission */
447 init_EUSART();
448
449 /* Setup RST and CS pins */
450 TRISCbits.TRISC0 = 0;
451 TRISCbits.TRISC1 = 0;
452
453 /* Reset */
454 PORTCbits.RC1 = 0;
455 Delay1KTCYx(1000);
456 PORTCbits.RC1 = 1;
457 Delay1KTCYx(1000);
458
459 /* Chip Select */
460 PORTCbits.RC0 = 0;
461
462 /* Display control */
463 n6610_write_command(DISCTL);
464 n6610_write_data(0x00); // P1: 0x00 = 2 divisions, switching period=8 (default)
465 n6610_write_data(0x04); // P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
466 n6610_write_data(0x00); // P3: 0x00 = no inversely highlighted lines
467
468 /* COM scan */
469 n6610_write_command(COMSCN);
470 n6610_write_data(0x80); // P1: 0x01 = Scan 1->80, 160<-81
471
472 /* Internal oscilator ON */
473 n6610_write_command(OSCON);
474
475 /* Sleep out */
476 n6610_write_command(SLPOUT);
477
478 /* Power control */
479 n6610_write_command(PWRCTR);
480 n6610_write_data(0xF0); // reference voltage regulator on, circuit voltage follower on, BOOST ON
481
482 /* Inverse display */
483 n6610_write_command(DISINV);
484
485 /* Data control */
486 n6610_write_command(DATCTL);
487 n6610_write_data(0x60); // P1: 0x05 = page address normal, col address inverted, address scan in page direction
488 n6610_write_data(0x00); // P2: 0x00 = RGB sequence (default value)
489 n6610_write_data(0x40); // P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A)
490
491 /* Voltage control (contrast setting) */
492 n6610_write_command(VOLCTR);
493 n6610_write_data(0x24); // P1 = 32 volume value (adjust this setting for your display 0 .. 63)
494 n6610_write_data(0xC0); // P2 = 3 resistance ratio (determined by experiment)
495
496 /* allow power supply to stabilize */
497 Delay1KTCYx(100);
498
499 /* turn on the display */
500 n6610_write_command(DISON);
501 }
502 #endif
503
504 #define CARD_TYPE_SD 0
505 #define CARD_TYPE_SDHC 1
506
507 uint8_t card_type;
508
509 /* SPI Send/Receive byte */
510 static uint8_t SPI(uint8_t d)
511 {
512 char received = 0;
513
514 SSPBUF = d;
515 while (SSPSTATbits.BF != 1);
516 received = SSPBUF;
517
518 return received;
519 }
520
521 /* Send a command to SD/MMC */
522 uint8_t card_command(uint8_t cmd, uint16_t addrH, uint16_t addrL, uint8_t crc)
523 {
524 SPI(0xFF);
525 SPI(cmd);
526 SPI((uint8_t) (addrH >> 8));
527 SPI((uint8_t) addrH);
528 SPI((uint8_t) (addrL >> 8));
529 SPI((uint8_t) addrL);
530 SPI(crc);
531 SPI(0xFF);
532 return SPI(0xFF); // return the last received character
533 }
534
535 /* Initalize SD/MMC Card */
536 uint8_t card_init(void)
537 {
538 uint8_t i;
539
540 /* Slow clock during card identification */
541 TRISCbits.TRISC3 = 0;
542 TRISCbits.TRISC5 = 0;
543 SSPCON1bits.SSPEN = 0;
544 SSPCON1 = 0x12; // CKP High, SPI Master, clock = Fosc/64
545 SSPSTATbits.SMP = 0;
546 //SSPSTATbits.SMP = 1;
547 SSPSTATbits.CKE = 0;
548 SSPCON1bits.SSPEN = 1;
549
550 /* Raise Chip Select */
551 TRISCbits.TRISC2 = 0;
552 PORTCbits.RC2 = 1;
553
554 /* Switch card to SPI Mode */
555 for(i = 0; i < 10; i ++)
556 SPI(0xFF);
557
558 /* Lower Chip Select */
559 PORTCbits.RC2 = 0;
560
561 /* Send CMD0 */
562 if (card_command(0x40, 0x0000, 0x0000, 0x95) != 0x01)
563 return 0;
564
565 card_type = CARD_TYPE_SD;
566 if ((card_command(0x48, 0x0000, 0x1AA, 0x87) & 4) == 0)
567 {
568 SPI(0xFF);
569 SPI(0xFF);
570 if ((SPI(0xFF) & 1) == 0)
571 return 0;
572 if (SPI(0xFF) != 0xAA)
573 return 0;
574
575 /* Send ACMD41 */
576 while (1)
577 {
578 uint8_t result;
579
580 card_command(0x77, 0x0000, 0x0000, 0xFF);
581 result = card_command(0x69, 0x4000, 0x0000, 0xFF);
582 if (result == 0x00)
583 break;
584 }
585
586 /* Send CMD58 */
587 if (card_command(0x7A, 0x0000, 0x0000, 0xFF))
588 return 0;
589
590 if(SPI(0xFF) & 0x40)
591 card_type = CARD_TYPE_SDHC;
592
593 SPI(0xFF);
594 SPI(0xFF);
595 SPI(0xFF);
596 }
597 else
598 {
599 /* Send CMD1 */
600 while (card_command(0x41, 0x0000, 0x0000, 0xFF) != 0x00);
601 }
602
603 /* Raise Chip Select */
604 PORTCbits.RC2 = 1;
605
606 /* Speed up the clock */
607 SSPCON1bits.SSPEN = 0;
608 //SSPCON1 = 0x11; // CKP High, SPI Master, clock = Fosc/16
609 SSPCON1 = 0x10; // CKP High, SPI Master, clock = Fosc/4
610 SSPSTATbits.SMP = 0;
611 //SSPSTATbits.SMP = 1;
612 SSPSTATbits.CKE = 0;
613 SSPCON1bits.SSPEN = 1;
614
615 return 1;
616 }
617
618 /* Reads one sector of 512 bytes from the card */
619 uint8_t card_read(uint32_t sector, uint8_t* buffer)
620 {
621 uint16_t i;
622 uint8_t result;
623 uint8_t card_response;
624
625 uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);
626
627 /* Lower Chip Select */
628 PORTCbits.RC2 = 0;
629
630 /* Send CMD17 */
631 result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);
632
633 while (result != 0)
634 result = SPI(0xFF);
635
636 /* Wait until 0xFE is received */
637 while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF);
638
639 if (card_response != 0xFE)
640 return 0;
641
642 /* Read data */
643 for(i = 0; i < 512; i ++)
644 buffer[i] = SPI(0xFF);
645
646 /* Receive CRC */
647 SPI(0xFF);
648 SPI(0xFF);
649
650 /* Let the card finish */
651 SPI(0xFF);
652
653 return 1;
654 }
655
656 #define LE16(card_sector, X) (((uint16_t) card_sector[(X)]) + \
657 (((uint16_t) card_sector[(X) + 1]) << 8))
658
659 #define LE32(card_sector, X) (((uint32_t) card_sector[(X)]) + \
660 (((uint32_t) card_sector[(X) + 1]) << 8) + \
661 (((uint32_t) card_sector[(X) + 2]) << 16) + \
662 (((uint32_t) card_sector[(X) + 3]) << 24))
663
664 #define LBA(X) (cluster_begin_lba + ((X) - 2) * sectors_per_cluster)
665
666 /* Initializes FAT32 support */
667 uint8_t fat32_init(void)
668 {
669 uint16_t bytes_per_sector;
670
671 /* Read sector 0 into the sector buffer */
672 if (!card_read(0, sector_buffer))
673 return 0;
674
675 /* Depending on whether SD Card controller firmware reports
676 * itself as removable media or not, it may or may not have an
677 * MBR. If there is no MBR, sector 0 will be the boot sector, as
678 * in a floppy. If the first byte of sector 0 is 0xEB, we assume
679 * it's the boot sector (LBR).
680 */
681
682 if (sector_buffer[0] != 0xEB)
683 {
684 /* Find out the starting sector of the first primary partition */
685 fpp_begin_lba = LE32(sector_buffer, 454);
686
687 /* Read FAT32 Volume ID into the sector buffer */
688 if (!card_read(fpp_begin_lba, sector_buffer))
689 return 0;
690 }
691 else
692 fpp_begin_lba = 0;
693
694 /* Compute important FAT locations */
695 reserved_sector_count = LE16(sector_buffer, 14);
696 fat_count = sector_buffer[16];
697 sectors_per_fat = LE32(sector_buffer, 36);
698
699 fat_begin_lba = fpp_begin_lba + reserved_sector_count;
700 cluster_begin_lba = fpp_begin_lba + reserved_sector_count + (fat_count * sectors_per_fat);
701
702 sectors_per_cluster = sector_buffer[13];
703 root_dir_first_cluster = LE32(sector_buffer, 44);
704
705 return 1;
706 }
707
708 /* Looks for Cumulus.BIN in the SD Card */
709 void update_firmware(void)
710 {
711 uint8_t i;
712 uint8_t s;
713 uint8_t* dir_entry;
714 uint32_t cluster;
715 uint32_t size;
716 uint16_t address;
717 int32_t bytes_left;
718 uint32_t sector;
719
720 if (!card_init())
721 goto error;
722 if (!fat32_init())
723 goto error;
724
725 /* Read directory first sector into the sector buffer */
726 if (!card_read(LBA(root_dir_first_cluster), sector_buffer))
727 goto error;
728
729 size = 0;
730 dir_entry = sector_buffer;
731
732 while (dir_entry[0])
733 {
734 for (i = 0; i < 11; i ++)
735 if (dir_entry[i] != str_cumulus_bin[i])
736 break;
737
738 if (i == 11)
739 {
740 /* Get the cluster number */
741 cluster = ((uint32_t) dir_entry[26]) +
742 ((uint32_t) dir_entry[27] << 8) +
743 ((uint32_t) dir_entry[20] << 16) +
744 ((uint32_t) dir_entry[21] << 24);
745
746 /* Get the size */
747 size = LE32(dir_entry, 28);
748
749 break;
750 }
751
752 dir_entry += 0x20;
753 }
754
755 if (size && size < 65536)
756 {
757 #ifdef TEXT_SUPPORT
758 n6610_draw_rom_str(2, 48, (const far rom char*) "Updating firmware");
759 #endif
760
761 s = 0;
762 address = 0;
763 bytes_left = size;
764 sector = LBA(cluster);
765
766 while (bytes_left > 0)
767 {
768 if (!card_read(sector, sector_buffer))
769 return;
770
771 for (i = 0; i < 8; i ++)
772 {
773 if (bytes_left <= 0)
774 break;
775
776 if (address >= 0x1000)
777 {
778 //n6610_debug_message_short(18 + i * 8, (const far rom char*) "Writing Block", address);
779 if (!erase_program_verify_page(address, sector_buffer + ((uint16_t) i) * 64))
780 goto error;
781 }
782
783 address += 64;
784 bytes_left -= 64;
785
786 //Delay10KTCYx(20);
787 }
788
789 n6610_fill_area(s, 56, 2, 16, 0xF0, 0x00, 0x0F);
790
791 s += 1;
792 sector ++;
793 }
794 }
795 else
796 goto error;
797
798 n6610_fill_area(0, 0, 132, 132, 0xF0, 0x00, 0x0F);
799 return;
800
801 error:
802
803 /* Turn screen to red */
804 n6610_fill_area(0, 0, 132, 132, 0x0F, 0xF0, 0x00);
805
806 #ifdef TEXT_SUPPORT
807 n6610_draw_rom_str(2, 48, (const far rom char*) "Update failed!");
808 #endif
809 }
810
811 void main(void)
812 {
813 OSCCON = 0x60; // IRCFx = 110 (8 MHz)
814 OSCTUNEbits.PLLEN = 1; // x4 PLL enabled = 32MHz
815
816 /* No Analog Pins */
817 ANSELH = 0x00;
818 ANSEL = 0x00;
819
820 /* Update firmware? */
821 if (PORTEbits.RE2 == 0 && PORTEbits.RE1 == 0)
822 {
823 n6610_init();
824 n6610_fill_area(0, 0, 132, 132, 0x00, 0x0F, 0xF0);
825
826 update_firmware();
827
828 /* Halt */
829 while (1);
830 }
831
832 _asm goto RM_RESET_VECTOR _endasm
833 }

  ViewVC Help
Powered by ViewVC 1.1.26