Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / bootloaders / stk500v2 / stk500boot.c @ 58d82c77

History | View | Annotate | Download (47.2 KB)

1
/*****************************************************************************
2
Title:     STK500v2 compatible bootloader
3
           Modified for Wiring board ATMega128-16MHz
4
Author:    Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
5
File:      $Id: stk500boot.c,v 1.11 2006/06/25 12:39:17 peter Exp $
6
Compiler:  avr-gcc 3.4.5 or 4.1 / avr-libc 1.4.3
7
Hardware:  All AVRs with bootloader support, tested with ATmega8
8
License:   GNU General Public License
9

10
Modified:  Worapoht Kornkaewwattanakul <dev@avride.com>   http://www.avride.com
11
Date:      17 October 2007
12
Update:    1st, 29 Dec 2007 : Enable CMD_SPI_MULTI but ignore unused command by return 0x00 byte response..
13
Compiler:  WINAVR20060421
14
Description: add timeout feature like previous Wiring bootloader
15

16
DESCRIPTION:
17
    This program allows an AVR with bootloader capabilities to
18
    read/write its own Flash/EEprom. To enter Programming mode
19
    an input pin is checked. If this pin is pulled low, programming mode
20
    is entered. If not, normal execution is done from $0000
21
    "reset" vector in Application area.
22
    Size fits into a 1024 word bootloader section
23
        when compiled with avr-gcc 4.1
24
        (direct replace on Wiring Board without fuse setting changed)
25

26
USAGE:
27
    - Set AVR MCU type and clock-frequency (F_CPU) in the Makefile.
28
    - Set baud rate below (AVRISP only works with 115200 bps)
29
    - compile/link the bootloader with the supplied Makefile
30
    - program the "Boot Flash section size" (BOOTSZ fuses),
31
      for boot-size 1024 words:  program BOOTSZ01
32
    - enable the BOOT Reset Vector (program BOOTRST)
33
    - Upload the hex file to the AVR using any ISP programmer
34
    - Program Boot Lock Mode 3 (program BootLock 11 and BootLock 12 lock bits) // (leave them)
35
    - Reset your AVR while keeping PROG_PIN pulled low // (for enter bootloader by switch)
36
    - Start AVRISP Programmer (AVRStudio/Tools/Program AVR)
37
    - AVRISP will detect the bootloader
38
    - Program your application FLASH file and optional EEPROM file using AVRISP
39

40
Note:
41
    Erasing the device without flashing, through AVRISP GUI button "Erase Device"
42
    is not implemented, due to AVRStudio limitations.
43
    Flash is always erased before programming.
44

45
        AVRdude:
46
        Please uncomment #define REMOVE_CMD_SPI_MULTI when using AVRdude.
47
        Comment #define REMOVE_PROGRAM_LOCK_BIT_SUPPORT to reduce code size
48
        Read Fuse Bits and Read/Write Lock Bits is not supported
49

50
NOTES:
51
    Based on Atmel Application Note AVR109 - Self-programming
52
    Based on Atmel Application Note AVR068 - STK500v2 Protocol
53

54
LICENSE:
55
    Copyright (C) 2006 Peter Fleury
56

57
    This program is free software; you can redistribute it and/or modify
58
    it under the terms of the GNU General Public License as published by
59
    the Free Software Foundation; either version 2 of the License, or
60
    any later version.
61

62
    This program is distributed in the hope that it will be useful,
63
    but WITHOUT ANY WARRANTY; without even the implied warranty of
64
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
65
    GNU General Public License for more details.
66

67
*****************************************************************************/
68

    
69
//************************************************************************
70
//*        Edit History
71
//************************************************************************
72
//*        Jul  7,        2010        <MLS> = Mark Sproul msproul@skycharoit.com
73
//*        Jul  7,        2010        <MLS> Working on mega2560. No Auto-restart
74
//*        Jul  7,        2010        <MLS> Switched to 8K bytes (4K words) so that we have room for the monitor
75
//*        Jul  8,        2010        <MLS> Found older version of source that had auto restart, put that code back in
76
//*        Jul  8,        2010        <MLS> Adding monitor code
77
//*        Jul 11,        2010        <MLS> Added blinking LED while waiting for download to start
78
//*        Jul 11,        2010        <MLS> Added EEPROM test
79
//*        Jul 29,        2010        <MLS> Added recchar_timeout for timing out on bootloading
80
//*        Aug 23,        2010        <MLS> Added support for atmega2561
81
//*        Aug 26,        2010        <MLS> Removed support for BOOT_BY_SWITCH
82
//************************************************************************
83

    
84

    
85

    
86
#include        <inttypes.h>
87
#include        <avr/io.h>
88
#include        <avr/interrupt.h>
89
#include        <avr/boot.h>
90
#include        <avr/pgmspace.h>
91
#include        <util/delay.h>
92
#include        <avr/eeprom.h>
93
#include        <avr/common.h>
94
#include        <stdlib.h>
95
#include        "command.h"
96

    
97

    
98
#if defined(_MEGA_BOARD_) || defined(_BOARD_AMBER128_) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
99
        #define                ENABLE_MONITOR
100
        static void        RunMonitor(void);
101
#endif
102

    
103
//#define        _DEBUG_SERIAL_
104
//#define        _DEBUG_WITH_LEDS_
105

    
106

    
107
/*
108
 * Uncomment the following lines to save code space
109
 */
110
//#define        REMOVE_PROGRAM_LOCK_BIT_SUPPORT                // disable program lock bits
111
//#define        REMOVE_BOOTLOADER_LED                                // no LED to show active bootloader
112
//#define        REMOVE_CMD_SPI_MULTI                                // disable processing of SPI_MULTI commands, Remark this line for AVRDUDE <Worapoht>
113
//
114

    
115

    
116

    
117
//************************************************************************
118
//*        LED on pin "PROGLED_PIN" on port "PROGLED_PORT"
119
//*        indicates that bootloader is active
120
//*        PG2 -> LED on Wiring board
121
//************************************************************************
122
#define                BLINK_LED_WHILE_WAITING
123

    
124
#ifdef _MEGA_BOARD_
125
        #define PROGLED_PORT        PORTB
126
        #define PROGLED_DDR                DDRB
127
        #define PROGLED_PIN                PINB7
128
#elif defined( _BOARD_AMBER128_ )
129
        //*        this is for the amber 128 http://www.soc-robotics.com/
130
        //*        onbarod led is PORTE4
131
        #define PROGLED_PORT        PORTD
132
        #define PROGLED_DDR                DDRD
133
        #define PROGLED_PIN                PINE7
134
#elif defined( _CEREBOTPLUS_BOARD_ )
135
        //*        this is for the Cerebot 2560 board
136
        //*        onbarod leds are on PORTE4-7
137
        #define PROGLED_PORT        PORTE
138
        #define PROGLED_DDR                DDRE
139
        #define PROGLED_PIN                PINE7
140
#elif defined( _PENGUINO_ )
141
        //*        this is for the Penguino
142
        //*        onbarod led is PORTE4
143
        #define PROGLED_PORT        PORTC
144
        #define PROGLED_DDR                DDRC
145
        #define PROGLED_PIN                PINC6
146
#elif defined( _ANDROID_2561_ ) || defined( __AVR_ATmega2561__ )
147
        //*        this is for the Boston Android 2561
148
        //*        onbarod led is PORTE4
149
        #define PROGLED_PORT        PORTA
150
        #define PROGLED_DDR                DDRA
151
        #define PROGLED_PIN                PINA3
152
#else
153
        #define PROGLED_PORT        PORTG
154
        #define PROGLED_DDR                DDRG
155
        #define PROGLED_PIN                PING2
156
#endif
157

    
158

    
159

    
160
/*
161
 * define CPU frequency in Mhz here if not defined in Makefile
162
 */
163
#ifndef F_CPU
164
        #define F_CPU 16000000UL
165
#endif
166

    
167
/*
168
 * UART Baudrate, AVRStudio AVRISP only accepts 115200 bps
169
 */
170

    
171
#ifndef BAUDRATE
172
        #define BAUDRATE 115200
173
#endif
174

    
175
/*
176
 *  Enable (1) or disable (0) USART double speed operation
177
 */
178
#ifndef UART_BAUDRATE_DOUBLE_SPEED
179
        #if defined (__AVR_ATmega32__)
180
                #define UART_BAUDRATE_DOUBLE_SPEED 0
181
        #else
182
                #define UART_BAUDRATE_DOUBLE_SPEED 1
183
        #endif
184
#endif
185

    
186
/*
187
 * HW and SW version, reported to AVRISP, must match version of AVRStudio
188
 */
189
#define CONFIG_PARAM_BUILD_NUMBER_LOW        0
190
#define CONFIG_PARAM_BUILD_NUMBER_HIGH        0
191
#define CONFIG_PARAM_HW_VER                                0x0F
192
#define CONFIG_PARAM_SW_MAJOR                        2
193
#define CONFIG_PARAM_SW_MINOR                        0x0A
194

    
195
/*
196
 * Calculate the address where the bootloader starts from FLASHEND and BOOTSIZE
197
 * (adjust BOOTSIZE below and BOOTLOADER_ADDRESS in Makefile if you want to change the size of the bootloader)
198
 */
199
//#define BOOTSIZE 1024
200
#if FLASHEND > 0x0F000
201
        #define BOOTSIZE 8192
202
#else
203
        #define BOOTSIZE 2048
204
#endif
205

    
206
#define APP_END  (FLASHEND -(2*BOOTSIZE) + 1)
207

    
208
/*
209
 * Signature bytes are not available in avr-gcc io_xxx.h
210
 */
211
#if defined (__AVR_ATmega8__)
212
        #define SIGNATURE_BYTES 0x1E9307
213
#elif defined (__AVR_ATmega16__)
214
        #define SIGNATURE_BYTES 0x1E9403
215
#elif defined (__AVR_ATmega32__)
216
        #define SIGNATURE_BYTES 0x1E9502
217
#elif defined (__AVR_ATmega8515__)
218
        #define SIGNATURE_BYTES 0x1E9306
219
#elif defined (__AVR_ATmega8535__)
220
        #define SIGNATURE_BYTES 0x1E9308
221
#elif defined (__AVR_ATmega162__)
222
        #define SIGNATURE_BYTES 0x1E9404
223
#elif defined (__AVR_ATmega128__)
224
        #define SIGNATURE_BYTES 0x1E9702
225
#elif defined (__AVR_ATmega1280__)
226
        #define SIGNATURE_BYTES 0x1E9703
227
#elif defined (__AVR_ATmega2560__)
228
        #define SIGNATURE_BYTES 0x1E9801
229
#elif defined (__AVR_ATmega2561__)
230
        #define SIGNATURE_BYTES 0x1e9802
231
#else
232
        #error "no signature definition for MCU available"
233
#endif
234

    
235

    
236
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
237
        || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
238
        /* ATMega8 with one USART */
239
        #define        UART_BAUD_RATE_LOW                        UBRRL
240
        #define        UART_STATUS_REG                                UCSRA
241
        #define        UART_CONTROL_REG                        UCSRB
242
        #define        UART_ENABLE_TRANSMITTER                TXEN
243
        #define        UART_ENABLE_RECEIVER                RXEN
244
        #define        UART_TRANSMIT_COMPLETE                TXC
245
        #define        UART_RECEIVE_COMPLETE                RXC
246
        #define        UART_DATA_REG                                UDR
247
        #define        UART_DOUBLE_SPEED                        U2X
248

    
249
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__) \
250
         || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
251
        /* ATMega with two USART, use UART0 */
252
        #define        UART_BAUD_RATE_LOW                        UBRR0L
253
        #define        UART_STATUS_REG                                UCSR0A
254
        #define        UART_CONTROL_REG                        UCSR0B
255
        #define        UART_ENABLE_TRANSMITTER                TXEN0
256
        #define        UART_ENABLE_RECEIVER                RXEN0
257
        #define        UART_TRANSMIT_COMPLETE                TXC0
258
        #define        UART_RECEIVE_COMPLETE                RXC0
259
        #define        UART_DATA_REG                                UDR0
260
        #define        UART_DOUBLE_SPEED                        U2X0
261
#else
262
        #error "no UART definition for MCU available"
263
#endif
264

    
265

    
266

    
267
/*
268
 * Macro to calculate UBBR from XTAL and baudrate
269
 */
270
#if defined(__AVR_ATmega32__) && UART_BAUDRATE_DOUBLE_SPEED
271
        #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 4 / baudRate - 1) / 2)
272
#elif defined(__AVR_ATmega32__)
273
        #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 8 / baudRate - 1) / 2)
274
#elif UART_BAUDRATE_DOUBLE_SPEED
275
        #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5)
276
#else
277
        #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*16.0)-1.0+0.5)
278
#endif
279

    
280

    
281
/*
282
 * States used in the receive state machine
283
 */
284
#define        ST_START                0
285
#define        ST_GET_SEQ_NUM        1
286
#define ST_MSG_SIZE_1        2
287
#define ST_MSG_SIZE_2        3
288
#define ST_GET_TOKEN        4
289
#define ST_GET_DATA                5
290
#define        ST_GET_CHECK        6
291
#define        ST_PROCESS                7
292

    
293
/*
294
 * use 16bit address variable for ATmegas with <= 64K flash
295
 */
296
#if defined(RAMPZ)
297
        typedef uint32_t address_t;
298
#else
299
        typedef uint16_t address_t;
300
#endif
301

    
302
/*
303
 * function prototypes
304
 */
305
static void sendchar(char c);
306
static unsigned char recchar(void);
307

    
308
/*
309
 * since this bootloader is not linked against the avr-gcc crt1 functions,
310
 * to reduce the code size, we need to provide our own initialization
311
 */
312
void __jumpMain        (void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
313
#include <avr/sfr_defs.h>
314

    
315
//#define        SPH_REG        0x3E
316
//#define        SPL_REG        0x3D
317

    
318
//*****************************************************************************
319
void __jumpMain(void)
320
{
321
//*        July 17, 2010        <MLS> Added stack pointer initialzation
322
//*        the first line did not do the job on the ATmega128
323

    
324
        asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
325

    
326
//        ldi r16,high(RAMEND)
327
//        out SPH,r16 ; Set stack pointer to top of RAM
328

    
329
//        asm volatile ( "ldi        16, 0x10");
330
        asm volatile ( "ldi        16, %0" :: "i" (RAMEND >> 8) );
331
//        asm volatile ( "out 0x3E,16");
332
//        asm volatile ( "out %0,16" :: "i" (SPH_REG) );
333
        asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_HI_ADDR) );
334

    
335
//        asm volatile ( "ldi        16, 0x00");
336
        asm volatile ( "ldi        16, %0" :: "i" (RAMEND & 0x0ff) );
337
//        asm volatile ( "out 0x3d,16");
338
//        asm volatile ( "out %0,16" :: "i" (SPL_REG) );
339
        asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_LO_ADDR) );
340

    
341

    
342

    
343
        asm volatile ( "clr __zero_reg__" );                                                                        // GCC depends on register r1 set to 0
344
        asm volatile ( "out %0, __zero_reg__" :: "I" (_SFR_IO_ADDR(SREG)) );        // set SREG to 0
345
//        asm volatile ( "rjmp main");                                                                                        // jump to main()
346
        asm volatile ( "jmp main");                                                                                                // jump to main()
347
}
348

    
349

    
350
//*****************************************************************************
351
void delay_ms(unsigned int timedelay)
352
{
353
        unsigned int i;
354
        for (i=0;i<timedelay;i++)
355
        {
356
                _delay_ms(0.5);
357
        }
358
}
359

    
360

    
361
//*****************************************************************************
362
/*
363
 * send single byte to USART, wait until transmission is completed
364
 */
365
static void sendchar(char c)
366
{
367
        UART_DATA_REG        =        c;                                                                                // prepare transmission
368
        while (!(UART_STATUS_REG & (1 << UART_TRANSMIT_COMPLETE)));        // wait until byte sent
369
        UART_STATUS_REG |= (1 << UART_TRANSMIT_COMPLETE);                        // delete TXCflag
370
}
371

    
372

    
373
//************************************************************************
374
static int        Serial_Available(void)
375
{
376
        return(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE));        // wait for data
377
}
378

    
379

    
380
//*****************************************************************************
381
/*
382
 * Read single byte from USART, block if no data available
383
 */
384
static unsigned char recchar(void)
385
{
386
        while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)))
387
        {
388
                // wait for data
389
        }
390
        return UART_DATA_REG;
391
}
392

    
393
#define        MAX_TIME_COUNT        (F_CPU >> 1)
394
//*****************************************************************************
395
static unsigned char recchar_timeout(void)
396
{
397
uint32_t count = 0;
398

    
399
        while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)))
400
        {
401
                // wait for data
402
                count++;
403
                if (count > MAX_TIME_COUNT)
404
                {
405
                unsigned int        data;
406
                #if (FLASHEND > 0x0FFFF)
407
                        data        =        pgm_read_word_far(0);        //*        get the first word of the user program
408
                #else
409
                        data        =        pgm_read_word_near(0);        //*        get the first word of the user program
410
                #endif
411
                        if (data != 0xffff)                                        //*        make sure its valid before jumping to it.
412
                        {
413
                                asm volatile(
414
                                                "clr        r30                \n\t"
415
                                                "clr        r31                \n\t"
416
                                                "ijmp        \n\t"
417
                                                );
418
                        }
419
                        count        =        0;
420
                }
421
        }
422
        return UART_DATA_REG;
423
}
424

    
425

    
426

    
427
//*****************************************************************************
428
int main(void)
429
{
430
        address_t                address                        =        0;
431
        address_t                eraseAddress        =        0;
432
        unsigned char        msgParseState;
433
        unsigned int        ii                                =        0;
434
        unsigned char        checksum                =        0;
435
        unsigned char        seqNum                        =        0;
436
        unsigned int        msgLength                =        0;
437
        unsigned char        msgBuffer[285];
438
        unsigned char        c, *p;
439
        unsigned char   isLeave = 0;
440

    
441
        unsigned long        boot_timeout;
442
        unsigned long        boot_timer;
443
        unsigned int        boot_state;
444
#ifdef ENABLE_MONITOR
445
        unsigned int        exPointCntr        =        0;
446
#endif
447

    
448

    
449
        boot_timer        =        0;
450
        boot_state        =        0;
451

    
452
#ifdef BLINK_LED_WHILE_WAITING
453
        boot_timeout        =         20000;                //*        should be about 1 second
454
//        boot_timeout        =        170000;
455
#else
456
        boot_timeout        =        3500000; // 7 seconds , approx 2us per step when optimize "s"
457
#endif
458
        /*
459
         * Branch to bootloader or application code ?
460
         */
461

    
462
#ifndef REMOVE_BOOTLOADER_LED
463
        /* PROG_PIN pulled low, indicate with LED that bootloader is active */
464
        PROGLED_DDR                |=        (1<<PROGLED_PIN);
465
//        PROGLED_PORT        &=        ~(1<<PROGLED_PIN);        // active low LED ON
466
        PROGLED_PORT        |=        (1<<PROGLED_PIN);        // active high LED ON
467

    
468
#ifdef _DEBUG_WITH_LEDS_
469
        for (ii=0; ii<3; ii++)
470
        {
471
                PROGLED_PORT        &=        ~(1<<PROGLED_PIN);        // turn LED off
472
                delay_ms(100);
473
                PROGLED_PORT        |=        (1<<PROGLED_PIN);        // turn LED on
474
                delay_ms(100);
475
        }
476
#endif
477

    
478
#endif
479
        /*
480
         * Init UART
481
         * set baudrate and enable USART receiver and transmiter without interrupts
482
         */
483
#if UART_BAUDRATE_DOUBLE_SPEED
484
        UART_STATUS_REG                |=        (1 <<UART_DOUBLE_SPEED);
485
#endif
486
        UART_BAUD_RATE_LOW        =        UART_BAUD_SELECT(BAUDRATE,F_CPU);
487
        UART_CONTROL_REG        =        (1 << UART_ENABLE_RECEIVER) | (1 << UART_ENABLE_TRANSMITTER);
488

    
489
        asm volatile ("nop");                        // wait until port has changed
490

    
491
#ifdef _DEBUG_SERIAL_
492
//        delay_ms(500);
493

    
494
        sendchar('s');
495
        sendchar('t');
496
        sendchar('k');
497
//        sendchar('5');
498
//        sendchar('0');
499
//        sendchar('0');
500
        sendchar('v');
501
        sendchar('2');
502
        sendchar(0x0d);
503
        sendchar(0x0a);
504

    
505
        delay_ms(100);
506
#endif
507

    
508
        while (boot_state==0)
509
        {
510
                while ((!(Serial_Available())) && (boot_state == 0))                // wait for data
511
                {
512
                        _delay_ms(0.001);
513
                        boot_timer++;
514
                        if (boot_timer > boot_timeout)
515
                        {
516
                                boot_state        =        1; // (after ++ -> boot_state=2 bootloader timeout, jump to main 0x00000 )
517
                        }
518
                #ifdef BLINK_LED_WHILE_WAITING
519
                        if ((boot_timer % 7000) == 0)
520
                        {
521
                                //*        toggle the LED
522
                                PROGLED_PORT        ^=        (1<<PROGLED_PIN);        // turn LED ON
523
                        }
524
                #endif
525
                }
526
                boot_state++; // ( if boot_state=1 bootloader received byte from UART, enter bootloader mode)
527
        }
528

    
529

    
530
        if (boot_state==1)
531
        {
532
                //*        main loop
533
                while (!isLeave)
534
                {
535
                        /*
536
                         * Collect received bytes to a complete message
537
                         */
538
                        msgParseState        =        ST_START;
539
                        while ( msgParseState != ST_PROCESS )
540
                        {
541
                                if (boot_state==1)
542
                                {
543
                                        boot_state        =        0;
544
                                        c                        =        UART_DATA_REG;
545
                                }
546
                                else
547
                                {
548
                                //        c        =        recchar();
549
                                        c        =        recchar_timeout();
550
                                }
551

    
552
                        #ifdef ENABLE_MONITOR
553
                                if (c == '!')
554
                                {
555
                                        exPointCntr++;
556
                                        if (exPointCntr == 3)
557
                                        {
558
                                                RunMonitor();
559
                                                exPointCntr                =        0;        //        reset back to zero so we dont get in an endless loop
560
                                                isLeave                        =        1;
561
                                                msgParseState        =        99;        //*        we dont want it do anything
562
                                                break;
563
                                        }
564
                                }
565
                                else
566
                                {
567
                                        exPointCntr        =        0;
568
                                }
569
                        #endif
570

    
571
                                switch (msgParseState)
572
                                {
573
                                        case ST_START:
574
                                                if ( c == MESSAGE_START )
575
                                                {
576
                                                        msgParseState        =        ST_GET_SEQ_NUM;
577
                                                        checksum                =        MESSAGE_START^0;
578
                                                }
579
                                                break;
580

    
581
                                        case ST_GET_SEQ_NUM:
582
                                                if ( (c == 1) || (c == seqNum) )
583
                                                {
584
                                                        seqNum                        =        c;
585
                                                        msgParseState        =        ST_MSG_SIZE_1;
586
                                                        checksum                ^=        c;
587
                                                }
588
                                                else
589
                                                {
590
                                                        msgParseState        =        ST_START;
591
                                                }
592
                                                break;
593

    
594
                                        case ST_MSG_SIZE_1:
595
                                                msgLength                =        c<<8;
596
                                                msgParseState        =        ST_MSG_SIZE_2;
597
                                                checksum                ^=        c;
598
                                                break;
599

    
600
                                        case ST_MSG_SIZE_2:
601
                                                msgLength                |=        c;
602
                                                msgParseState        =        ST_GET_TOKEN;
603
                                                checksum                ^=        c;
604
                                                break;
605

    
606
                                        case ST_GET_TOKEN:
607
                                                if ( c == TOKEN )
608
                                                {
609
                                                        msgParseState        =        ST_GET_DATA;
610
                                                        checksum                ^=        c;
611
                                                        ii                                =        0;
612
                                                }
613
                                                else
614
                                                {
615
                                                        msgParseState        =        ST_START;
616
                                                }
617
                                                break;
618

    
619
                                        case ST_GET_DATA:
620
                                                msgBuffer[ii++]        =        c;
621
                                                checksum                ^=        c;
622
                                                if (ii == msgLength )
623
                                                {
624
                                                        msgParseState        =        ST_GET_CHECK;
625
                                                }
626
                                                break;
627

    
628
                                        case ST_GET_CHECK:
629
                                                if ( c == checksum )
630
                                                {
631
                                                        msgParseState        =        ST_PROCESS;
632
                                                }
633
                                                else
634
                                                {
635
                                                        msgParseState        =        ST_START;
636
                                                }
637
                                                break;
638
                                }        //        switch
639
                        }        //        while(msgParseState)
640

    
641
                        /*
642
                         * Now process the STK500 commands, see Atmel Appnote AVR068
643
                         */
644

    
645
                        switch (msgBuffer[0])
646
                        {
647
        #ifndef REMOVE_CMD_SPI_MULTI
648
                                case CMD_SPI_MULTI:
649
                                        {
650
                                                unsigned char answerByte;
651
                                                unsigned char flag=0;
652

    
653
                                                if ( msgBuffer[4]== 0x30 )
654
                                                {
655
                                                        unsigned char signatureIndex        =        msgBuffer[6];
656

    
657
                                                        if ( signatureIndex == 0 )
658
                                                                answerByte        =        (SIGNATURE_BYTES >>16) & 0x000000FF;
659
                                                        else if ( signatureIndex == 1 )
660
                                                                answerByte        =        (SIGNATURE_BYTES >> 8) & 0x000000FF;
661
                                                        else
662
                                                                answerByte        =        SIGNATURE_BYTES & 0x000000FF;
663
                                                }
664
                                                else if ( msgBuffer[4] & 0x50 )
665
                                                {
666
                                                        answerByte        =        0; //read fuse/lock bits not implemented, return dummy value
667
                                                }
668
                                                else
669
                                                {
670
                                                        answerByte        =        0; // for all others command are not implemented, return dummy value for AVRDUDE happy <Worapoht>
671
        //                                                flag        =        1; // Remark this line for AVRDUDE <Worapoht>
672
                                                }
673
                                                if ( !flag )
674
                                                {
675
                                                        msgLength                =        7;
676
                                                        msgBuffer[1]        =        STATUS_CMD_OK;
677
                                                        msgBuffer[2]        =        0;
678
                                                        msgBuffer[3]        =        msgBuffer[4];
679
                                                        msgBuffer[4]        =        0;
680
                                                        msgBuffer[5]        =        answerByte;
681
                                                        msgBuffer[6]        =        STATUS_CMD_OK;
682
                                                }
683
                                        }
684
                                        break;
685
        #endif
686
                                case CMD_SIGN_ON:
687
                                        msgLength                =        11;
688
                                        msgBuffer[1]         =        STATUS_CMD_OK;
689
                                        msgBuffer[2]         =        8;
690
                                        msgBuffer[3]         =        'A';
691
                                        msgBuffer[4]         =        'V';
692
                                        msgBuffer[5]         =        'R';
693
                                        msgBuffer[6]         =        'I';
694
                                        msgBuffer[7]         =        'S';
695
                                        msgBuffer[8]         =        'P';
696
                                        msgBuffer[9]         =        '_';
697
                                        msgBuffer[10]        =        '2';
698
                                        break;
699

    
700
                                case CMD_GET_PARAMETER:
701
                                        {
702
                                                unsigned char value;
703

    
704
                                                switch(msgBuffer[1])
705
                                                {
706
                                                case PARAM_BUILD_NUMBER_LOW:
707
                                                        value        =        CONFIG_PARAM_BUILD_NUMBER_LOW;
708
                                                        break;
709
                                                case PARAM_BUILD_NUMBER_HIGH:
710
                                                        value        =        CONFIG_PARAM_BUILD_NUMBER_HIGH;
711
                                                        break;
712
                                                case PARAM_HW_VER:
713
                                                        value        =        CONFIG_PARAM_HW_VER;
714
                                                        break;
715
                                                case PARAM_SW_MAJOR:
716
                                                        value        =        CONFIG_PARAM_SW_MAJOR;
717
                                                        break;
718
                                                case PARAM_SW_MINOR:
719
                                                        value        =        CONFIG_PARAM_SW_MINOR;
720
                                                        break;
721
                                                default:
722
                                                        value        =        0;
723
                                                        break;
724
                                                }
725
                                                msgLength                =        3;
726
                                                msgBuffer[1]        =        STATUS_CMD_OK;
727
                                                msgBuffer[2]        =        value;
728
                                        }
729
                                        break;
730

    
731
                                case CMD_LEAVE_PROGMODE_ISP:
732
                                        isLeave        =        1;
733
                                        //*        fall thru
734

    
735
                                case CMD_SET_PARAMETER:
736
                                case CMD_ENTER_PROGMODE_ISP:
737
                                        msgLength                =        2;
738
                                        msgBuffer[1]        =        STATUS_CMD_OK;
739
                                        break;
740

    
741
                                case CMD_READ_SIGNATURE_ISP:
742
                                        {
743
                                                unsigned char signatureIndex        =        msgBuffer[4];
744
                                                unsigned char signature;
745

    
746
                                                if ( signatureIndex == 0 )
747
                                                        signature        =        (SIGNATURE_BYTES >>16) & 0x000000FF;
748
                                                else if ( signatureIndex == 1 )
749
                                                        signature        =        (SIGNATURE_BYTES >> 8) & 0x000000FF;
750
                                                else
751
                                                        signature        =        SIGNATURE_BYTES & 0x000000FF;
752

    
753
                                                msgLength                =        4;
754
                                                msgBuffer[1]        =        STATUS_CMD_OK;
755
                                                msgBuffer[2]        =        signature;
756
                                                msgBuffer[3]        =        STATUS_CMD_OK;
757
                                        }
758
                                        break;
759

    
760
                                case CMD_READ_LOCK_ISP:
761
                                        msgLength                =        4;
762
                                        msgBuffer[1]        =        STATUS_CMD_OK;
763
                                        msgBuffer[2]        =        boot_lock_fuse_bits_get( GET_LOCK_BITS );
764
                                        msgBuffer[3]        =        STATUS_CMD_OK;
765
                                        break;
766

    
767
                                case CMD_READ_FUSE_ISP:
768
                                        {
769
                                                unsigned char fuseBits;
770

    
771
                                                if ( msgBuffer[2] == 0x50 )
772
                                                {
773
                                                        if ( msgBuffer[3] == 0x08 )
774
                                                                fuseBits        =        boot_lock_fuse_bits_get( GET_EXTENDED_FUSE_BITS );
775
                                                        else
776
                                                                fuseBits        =        boot_lock_fuse_bits_get( GET_LOW_FUSE_BITS );
777
                                                }
778
                                                else
779
                                                {
780
                                                        fuseBits        =        boot_lock_fuse_bits_get( GET_HIGH_FUSE_BITS );
781
                                                }
782
                                                msgLength                =        4;
783
                                                msgBuffer[1]        =        STATUS_CMD_OK;
784
                                                msgBuffer[2]        =        fuseBits;
785
                                                msgBuffer[3]        =        STATUS_CMD_OK;
786
                                        }
787
                                        break;
788

    
789
        #ifndef REMOVE_PROGRAM_LOCK_BIT_SUPPORT
790
                                case CMD_PROGRAM_LOCK_ISP:
791
                                        {
792
                                                unsigned char lockBits        =        msgBuffer[4];
793

    
794
                                                lockBits        =        (~lockBits) & 0x3C;        // mask BLBxx bits
795
                                                boot_lock_bits_set(lockBits);                // and program it
796
                                                boot_spm_busy_wait();
797

    
798
                                                msgLength                =        3;
799
                                                msgBuffer[1]        =        STATUS_CMD_OK;
800
                                                msgBuffer[2]        =        STATUS_CMD_OK;
801
                                        }
802
                                        break;
803
        #endif
804
                                case CMD_CHIP_ERASE_ISP:
805
                                        eraseAddress        =        0;
806
                                        msgLength                =        2;
807
                                        msgBuffer[1]        =        STATUS_CMD_OK;
808
                                        break;
809

    
810
                                case CMD_LOAD_ADDRESS:
811
        #if defined(RAMPZ)
812
                                        address        =        ( ((address_t)(msgBuffer[1])<<24)|((address_t)(msgBuffer[2])<<16)|((address_t)(msgBuffer[3])<<8)|(msgBuffer[4]) )<<1;
813
        #else
814
                                        address        =        ( ((msgBuffer[3])<<8)|(msgBuffer[4]) )<<1;                //convert word to byte address
815
        #endif
816
                                        msgLength                =        2;
817
                                        msgBuffer[1]        =        STATUS_CMD_OK;
818
                                        break;
819

    
820
                                case CMD_PROGRAM_FLASH_ISP:
821
                                case CMD_PROGRAM_EEPROM_ISP:
822
                                        {
823
                                                unsigned int        size        =        ((msgBuffer[1])<<8) | msgBuffer[2];
824
                                                unsigned char        *p        =        msgBuffer+10;
825
                                                unsigned int        data;
826
                                                unsigned char        highByte, lowByte;
827
                                                address_t                tempaddress        =        address;
828

    
829

    
830
                                                if ( msgBuffer[0] == CMD_PROGRAM_FLASH_ISP )
831
                                                {
832
                                                        // erase only main section (bootloader protection)
833
                                                        if (eraseAddress < APP_END )
834
                                                        {
835
                                                                boot_page_erase(eraseAddress);        // Perform page erase
836
                                                                boot_spm_busy_wait();                // Wait until the memory is erased.
837
                                                                eraseAddress += SPM_PAGESIZE;        // point to next page to be erase
838
                                                        }
839

    
840
                                                        /* Write FLASH */
841
                                                        do {
842
                                                                lowByte                =        *p++;
843
                                                                highByte         =        *p++;
844

    
845
                                                                data                =        (highByte << 8) | lowByte;
846
                                                                boot_page_fill(address,data);
847

    
848
                                                                address        =        address + 2;        // Select next word in memory
849
                                                                size        -=        2;                                // Reduce number of bytes to write by two
850
                                                        } while (size);                                        // Loop until all bytes written
851

    
852
                                                        boot_page_write(tempaddress);
853
                                                        boot_spm_busy_wait();
854
                                                        boot_rww_enable();                                // Re-enable the RWW section
855
                                                }
856
                                                else
857
                                                {
858
                                                #if (!defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__)  && !defined(__AVR_ATmega2561__))
859
                                                        /* write EEPROM */
860
                                                        do {
861
                                                                EEARL        =        address;                        // Setup EEPROM address
862
                                                                EEARH        =        (address >> 8);
863
                                                                address++;                                                // Select next EEPROM byte
864

    
865
                                                                EEDR        =        *p++;                                // get byte from buffer
866
                                                                EECR        |=        (1<<EEMWE);                        // Write data into EEPROM
867
                                                                EECR        |=        (1<<EEWE);
868

    
869
                                                                while (EECR & (1<<EEWE));        // Wait for write operation to finish
870
                                                                size--;                                                // Decrease number of bytes to write
871
                                                        } while (size);                                        // Loop until all bytes written
872
                                                #endif
873
                                                }
874
                                                        msgLength        =        2;
875
                                                msgBuffer[1]        =        STATUS_CMD_OK;
876
                                        }
877
                                        break;
878

    
879
                                case CMD_READ_FLASH_ISP:
880
                                case CMD_READ_EEPROM_ISP:
881
                                        {
882
                                                unsigned int        size        =        ((msgBuffer[1])<<8) | msgBuffer[2];
883
                                                unsigned char        *p                =        msgBuffer+1;
884
                                                msgLength                                =        size+3;
885

    
886
                                                *p++        =        STATUS_CMD_OK;
887
                                                if (msgBuffer[0] == CMD_READ_FLASH_ISP )
888
                                                {
889
                                                        unsigned int data;
890

    
891
                                                        // Read FLASH
892
                                                        do {
893
        #if defined(RAMPZ)
894
                                                                data        =        pgm_read_word_far(address);
895
        #else
896
                                                                data        =        pgm_read_word_near(address);
897
        #endif
898
                                                                *p++        =        (unsigned char)data;                //LSB
899
                                                                *p++        =        (unsigned char)(data >> 8);        //MSB
900
                                                                address        +=        2;                                                        // Select next word in memory
901
                                                                size        -=        2;
902
                                                        }while (size);
903
                                                }
904
                                                else
905
                                                {
906
                                                        /* Read EEPROM */
907
                                                        do {
908
                                                                EEARL        =        address;                        // Setup EEPROM address
909
                                                                EEARH        =        ((address >> 8));
910
                                                                address++;                                        // Select next EEPROM byte
911
                                                                EECR        |=        (1<<EERE);                        // Read EEPROM
912
                                                                *p++        =        EEDR;                                // Send EEPROM data
913
                                                                size--;
914
                                                        } while (size);
915
                                                }
916
                                                *p++        =        STATUS_CMD_OK;
917
                                        }
918
                                        break;
919

    
920
                                default:
921
                                        msgLength                =        2;
922
                                        msgBuffer[1]        =        STATUS_CMD_FAILED;
923
                                        break;
924
                        }
925

    
926
                        /*
927
                         * Now send answer message back
928
                         */
929
                        sendchar(MESSAGE_START);
930
                        checksum        =        MESSAGE_START^0;
931

    
932
                        sendchar(seqNum);
933
                        checksum        ^=        seqNum;
934

    
935
                        c                        =        ((msgLength>>8)&0xFF);
936
                        sendchar(c);
937
                        checksum        ^=        c;
938

    
939
                        c                        =        msgLength&0x00FF;
940
                        sendchar(c);
941
                        checksum ^= c;
942

    
943
                        sendchar(TOKEN);
944
                        checksum ^= TOKEN;
945

    
946
                        p        =        msgBuffer;
947
                        while ( msgLength )
948
                        {
949
                                c        =        *p++;
950
                                sendchar(c);
951
                                checksum ^=c;
952
                                msgLength--;
953
                        }
954
                        sendchar(checksum);
955
                        seqNum++;
956
        
957
                #ifndef REMOVE_BOOTLOADER_LED
958
                        //*        <MLS>        toggle the LED
959
                        PROGLED_PORT        ^=        (1<<PROGLED_PIN);        // active high LED ON
960
                #endif
961

    
962
                }
963
        }
964

    
965
#ifdef _DEBUG_WITH_LEDS_
966
        //*        this is for debugging it can be removed
967
        for (ii=0; ii<10; ii++)
968
        {
969
                PROGLED_PORT        &=        ~(1<<PROGLED_PIN);        // turn LED off
970
                delay_ms(200);
971
                PROGLED_PORT        |=        (1<<PROGLED_PIN);        // turn LED on
972
                delay_ms(200);
973
        }
974
        PROGLED_PORT        &=        ~(1<<PROGLED_PIN);        // turn LED off
975
#endif
976

    
977
#ifdef _DEBUG_SERIAL_
978
        sendchar('j');
979
//        sendchar('u');
980
//        sendchar('m');
981
//        sendchar('p');
982
//        sendchar(' ');
983
//        sendchar('u');
984
//        sendchar('s');
985
//        sendchar('r');
986
        sendchar(0x0d);
987
        sendchar(0x0a);
988

    
989
        delay_ms(100);
990
#endif
991

    
992

    
993
#ifndef REMOVE_BOOTLOADER_LED
994
        PROGLED_DDR                &=        ~(1<<PROGLED_PIN);        // set to default
995
        PROGLED_PORT        &=        ~(1<<PROGLED_PIN);        // active low LED OFF
996
//        PROGLED_PORT        |=        (1<<PROGLED_PIN);        // active high LED OFf
997
        delay_ms(100);                                                        // delay after exit
998
#endif
999

    
1000

    
1001
        asm volatile ("nop");                        // wait until port has changed
1002

    
1003
        /*
1004
         * Now leave bootloader
1005
         */
1006

    
1007
        UART_STATUS_REG        &=        0xfd;
1008
        boot_rww_enable();                                // enable application section
1009

    
1010

    
1011
        asm volatile(
1012
                        "clr        r30                \n\t"
1013
                        "clr        r31                \n\t"
1014
                        "ijmp        \n\t"
1015
                        );
1016
//        asm volatile ( "push r1" "\n\t"                // Jump to Reset vector in Application Section
1017
//                                        "push r1" "\n\t"
1018
//                                        "ret"         "\n\t"
1019
//                                        ::);
1020

    
1021
         /*
1022
         * Never return to stop GCC to generate exit return code
1023
         * Actually we will never reach this point, but the compiler doesn't
1024
         * understand this
1025
         */
1026
        for(;;);
1027
}
1028

    
1029
/*
1030
base address = f800
1031

1032
avrdude: Device signature = 0x1e9703
1033
avrdude: safemode: lfuse reads as FF
1034
avrdude: safemode: hfuse reads as DA
1035
avrdude: safemode: efuse reads as F5
1036
avrdude>
1037

1038

1039
base address = f000
1040
avrdude: Device signature = 0x1e9703
1041
avrdude: safemode: lfuse reads as FF
1042
avrdude: safemode: hfuse reads as D8
1043
avrdude: safemode: efuse reads as F5
1044
avrdude>
1045
*/
1046

    
1047
//************************************************************************
1048
#ifdef ENABLE_MONITOR
1049
#include        <math.h>
1050

    
1051
unsigned long        gRamIndex;
1052
unsigned long        gFlashIndex;
1053
unsigned long        gEepromIndex;
1054

    
1055

    
1056
#define        true        1
1057
#define        false        0
1058

    
1059
#if defined(__AVR_ATmega128__)
1060
        #define        kCPU_NAME        "ATmega128"
1061
#elif defined(__AVR_ATmega1280__)
1062
        #define        kCPU_NAME        "ATmega1280"
1063
#elif defined(__AVR_ATmega1281__)
1064
        #define        kCPU_NAME        "ATmega1281"
1065
#elif defined(__AVR_ATmega2560__)
1066
        #define        kCPU_NAME        "ATmega2560"
1067
#elif defined(__AVR_ATmega2561__)
1068
        #define        kCPU_NAME        "ATmega2561"
1069
#endif
1070

    
1071
#ifdef _VECTORS_SIZE
1072
        #define        kInterruptVectorCount (_VECTORS_SIZE / 4)
1073
#else
1074
        #define        kInterruptVectorCount 23
1075
#endif
1076

    
1077

    
1078
void        PrintDecInt(int theNumber, int digitCnt);
1079

    
1080
#ifdef kCPU_NAME
1081
        prog_char        gTextMsg_CPU_Name[]                        PROGMEM        =        kCPU_NAME;
1082
#else
1083
        prog_char        gTextMsg_CPU_Name[]                        PROGMEM        =        "UNKNOWN";
1084
#endif
1085

    
1086
        prog_char        gTextMsg_Explorer[]                        PROGMEM        =        "Arduino explorer stk500V2 by MLS";
1087
        prog_char        gTextMsg_Prompt[]                        PROGMEM        =        "Bootloader>";
1088
        prog_char        gTextMsg_HUH[]                                PROGMEM        =        "Huh?";
1089
        prog_char        gTextMsg_COMPILED_ON[]                PROGMEM        =        "Compiled on  = ";
1090
        prog_char        gTextMsg_CPU_Type[]                        PROGMEM        =        "CPU Type     = ";
1091
        prog_char        gTextMsg_AVR_ARCH[]                        PROGMEM        =        "__AVR_ARCH__ = ";
1092
        prog_char        gTextMsg_AVR_LIBC[]                        PROGMEM        =        "AVR LibC Ver = ";
1093
        prog_char        gTextMsg_GCC_VERSION[]                PROGMEM        =        "GCC Version  = ";
1094
        prog_char        gTextMsg_CPU_SIGNATURE[]        PROGMEM        =        "CPU signature= ";
1095
        prog_char        gTextMsg_FUSE_BYTE_LOW[]        PROGMEM        =        "Low fuse     = ";
1096
        prog_char        gTextMsg_FUSE_BYTE_HIGH[]        PROGMEM        =        "High fuse    = ";
1097
        prog_char        gTextMsg_FUSE_BYTE_EXT[]        PROGMEM        =        "Ext fuse     = ";
1098
        prog_char        gTextMsg_FUSE_BYTE_LOCK[]        PROGMEM        =        "Lock fuse    = ";
1099
        prog_char        gTextMsg_GCC_DATE_STR[]                PROGMEM        =        __DATE__;
1100
        prog_char        gTextMsg_AVR_LIBC_VER_STR[]        PROGMEM        =        __AVR_LIBC_VERSION_STRING__;
1101
        prog_char        gTextMsg_GCC_VERSION_STR[]        PROGMEM        =        __VERSION__;
1102
        prog_char        gTextMsg_VECTOR_HEADER[]        PROGMEM        =        "V#   ADDR   op code     instruction addr   Interrupt";
1103
        prog_char        gTextMsg_noVector[]                        PROGMEM        =        "no vector";
1104
        prog_char        gTextMsg_rjmp[]                                PROGMEM        =        "rjmp  ";
1105
        prog_char        gTextMsg_jmp[]                                PROGMEM        =        "jmp ";
1106
        prog_char        gTextMsg_WHAT_PORT[]                PROGMEM        =        "What port:";
1107
        prog_char        gTextMsg_PortNotSupported[]        PROGMEM        =        "Port not supported";
1108
        prog_char        gTextMsg_MustBeLetter[]                PROGMEM        =        "Must be a letter";
1109
        prog_char        gTextMsg_SPACE[]                        PROGMEM        =        " ";
1110
        prog_char        gTextMsg_WriteToEEprom[]        PROGMEM        =        "Writting EE";
1111
        prog_char        gTextMsg_ReadingEEprom[]        PROGMEM        =        "Reading EE";
1112
        prog_char        gTextMsg_EEPROMerrorCnt[]        PROGMEM        =        "eeprom error count=";
1113
        prog_char        gTextMsg_PORT[]                                PROGMEM        =        "PORT";
1114

    
1115

    
1116
//************************************************************************
1117
//*        Help messages
1118
        prog_char        gTextMsg_HELP_MSG_0[]                PROGMEM        =        "0=Zero address ctrs";
1119
        prog_char        gTextMsg_HELP_MSG_QM[]                PROGMEM        =        "?=CPU stats";
1120
        prog_char        gTextMsg_HELP_MSG_AT[]                PROGMEM        =        "@=EEPROM test";
1121
        prog_char        gTextMsg_HELP_MSG_B[]                PROGMEM        =        "B=Blink LED";
1122
        prog_char        gTextMsg_HELP_MSG_E[]                PROGMEM        =        "E=Dump EEPROM";
1123
        prog_char        gTextMsg_HELP_MSG_F[]                PROGMEM        =        "F=Dump FLASH";
1124
        prog_char        gTextMsg_HELP_MSG_H[]                PROGMEM        =        "H=Help";
1125
        prog_char        gTextMsg_HELP_MSG_L[]                PROGMEM        =        "L=List I/O Ports";
1126
        prog_char        gTextMsg_HELP_MSG_Q[]                PROGMEM        =        "Q=Quit & jump to user pgm";
1127
        prog_char        gTextMsg_HELP_MSG_R[]                PROGMEM        =        "R=Dump RAM";
1128
        prog_char        gTextMsg_HELP_MSG_V[]                PROGMEM        =        "V=show interrupt Vectors";
1129
        prog_char        gTextMsg_HELP_MSG_Y[]                PROGMEM        =        "Y=Port blink";
1130

    
1131
        prog_char        gTextMsg_END[]                                PROGMEM        =        "*";
1132

    
1133

    
1134
//************************************************************************
1135
void        PrintFromPROGMEM(void *dataPtr, unsigned char offset)
1136
{
1137
uint8_t        ii;
1138
char        theChar;
1139

    
1140
        ii                        =        offset;
1141
        theChar                =        1;
1142

    
1143
        while (theChar != 0)
1144
        {
1145
                theChar        =        pgm_read_byte_far((uint32_t)dataPtr + ii);
1146
                if (theChar != 0)
1147
                {
1148
                        sendchar(theChar);
1149
                }
1150
                ii++;
1151
        }
1152
}
1153

    
1154
//************************************************************************
1155
void        PrintNewLine(void)
1156
{
1157
        sendchar(0x0d);
1158
        sendchar(0x0a);
1159
}
1160

    
1161

    
1162
//************************************************************************
1163
void        PrintFromPROGMEMln(void *dataPtr, unsigned char offset)
1164
{
1165
        PrintFromPROGMEM(dataPtr, offset);
1166

    
1167
        PrintNewLine();
1168
}
1169

    
1170

    
1171
//************************************************************************
1172
void        PrintString(char *textString)
1173
{
1174
char        theChar;
1175
int                ii;
1176

    
1177
        theChar                =        1;
1178
        ii                        =        0;
1179
        while (theChar != 0)
1180
        {
1181
                theChar        =        textString[ii];
1182
                if (theChar != 0)
1183
                {
1184
                        sendchar(theChar);
1185
                }
1186
                ii++;
1187
        }
1188
}
1189

    
1190
//************************************************************************
1191
void        PrintHexByte(unsigned char theByte)
1192
{
1193
char        theChar;
1194

    
1195
        theChar        =        0x30 + ((theByte >> 4) & 0x0f);
1196
        if (theChar > 0x39)
1197
        {
1198
                theChar        +=        7;
1199
        }
1200
        sendchar(theChar );
1201

    
1202
        theChar        =        0x30 + (theByte & 0x0f);
1203
        if (theChar > 0x39)
1204
        {
1205
                theChar        +=        7;
1206
        }
1207
        sendchar(theChar );
1208
}
1209

    
1210
//************************************************************************
1211
void        PrintDecInt(int theNumber, int digitCnt)
1212
{
1213
int        theChar;
1214
int        myNumber;
1215

    
1216
        myNumber        =        theNumber;
1217

    
1218
        if ((myNumber > 100) || (digitCnt >= 3))
1219
        {
1220
                theChar                =        0x30 + myNumber / 100;
1221
                sendchar(theChar );
1222
        }
1223

    
1224
        if ((myNumber > 10) || (digitCnt >= 2))
1225
        {
1226
                theChar        =        0x30  + ((myNumber % 100) / 10 );
1227
                sendchar(theChar );
1228
        }
1229
        theChar        =        0x30 + (myNumber % 10);
1230
        sendchar(theChar );
1231
}
1232

    
1233

    
1234

    
1235

    
1236
//************************************************************************
1237
static void        PrintCPUstats(void)
1238
{
1239
unsigned char fuseByte;
1240

    
1241
        PrintFromPROGMEMln(gTextMsg_Explorer, 0);
1242

    
1243
        PrintFromPROGMEM(gTextMsg_COMPILED_ON, 0);
1244
        PrintFromPROGMEMln(gTextMsg_GCC_DATE_STR, 0);
1245

    
1246
        PrintFromPROGMEM(gTextMsg_CPU_Type, 0);
1247
        PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
1248

    
1249
        PrintFromPROGMEM(gTextMsg_AVR_ARCH, 0);
1250
        PrintDecInt(__AVR_ARCH__, 1);
1251
        PrintNewLine();
1252

    
1253
        PrintFromPROGMEM(gTextMsg_GCC_VERSION, 0);
1254
        PrintFromPROGMEMln(gTextMsg_GCC_VERSION_STR, 0);
1255

    
1256
        //*        these can be found in avr/version.h
1257
        PrintFromPROGMEM(gTextMsg_AVR_LIBC, 0);
1258
        PrintFromPROGMEMln(gTextMsg_AVR_LIBC_VER_STR, 0);
1259

    
1260
#if defined(SIGNATURE_0)
1261
        PrintFromPROGMEM(gTextMsg_CPU_SIGNATURE, 0);
1262
        //*        these can be found in avr/iomxxx.h
1263
        PrintHexByte(SIGNATURE_0);
1264
        PrintHexByte(SIGNATURE_1);
1265
        PrintHexByte(SIGNATURE_2);
1266
        PrintNewLine();
1267
#endif
1268

    
1269

    
1270
#if defined(GET_LOW_FUSE_BITS)
1271
        //*        fuse settings
1272
        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOW, 0);
1273
        fuseByte        =        boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
1274
        PrintHexByte(fuseByte);
1275
        PrintNewLine();
1276

    
1277
        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_HIGH, 0);
1278
        fuseByte        =        boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
1279
        PrintHexByte(fuseByte);
1280
        PrintNewLine();
1281

    
1282
        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_EXT, 0);
1283
        fuseByte        =        boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
1284
        PrintHexByte(fuseByte);
1285
        PrintNewLine();
1286

    
1287
        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOCK, 0);
1288
        fuseByte        =        boot_lock_fuse_bits_get(GET_LOCK_BITS);
1289
        PrintHexByte(fuseByte);
1290
        PrintNewLine();
1291

    
1292
#endif
1293

    
1294
}
1295

    
1296
#ifndef sbi
1297
        #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
1298
#endif
1299

    
1300
//************************************************************************
1301
int analogRead(uint8_t pin)
1302
{
1303
uint8_t low, high;
1304

    
1305
        // set the analog reference (high two bits of ADMUX) and select the
1306
        // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
1307
        // to 0 (the default).
1308
//        ADMUX        =        (analog_reference << 6) | (pin & 0x07);
1309
        ADMUX        =        (1 << 6) | (pin & 0x07);
1310

    
1311
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
1312
        // the MUX5 bit of ADCSRB selects whether we're reading from channels
1313
        // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
1314
        ADCSRB        =        (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
1315
#endif
1316

    
1317
        // without a delay, we seem to read from the wrong channel
1318
        //delay(1);
1319

    
1320
        // start the conversion
1321
        sbi(ADCSRA, ADSC);
1322

    
1323
        // ADSC is cleared when the conversion finishes
1324
        while (bit_is_set(ADCSRA, ADSC));
1325

    
1326
        // we have to read ADCL first; doing so locks both ADCL
1327
        // and ADCH until ADCH is read.  reading ADCL second would
1328
        // cause the results of each conversion to be discarded,
1329
        // as ADCL and ADCH would be locked when it completed.
1330
        low                =        ADCL;
1331
        high        =        ADCH;
1332

    
1333
        // combine the two bytes
1334
        return (high << 8) | low;
1335
}
1336

    
1337
//************************************************************************
1338
static void BlinkLED(void)
1339
{
1340
        PROGLED_DDR                |=        (1<<PROGLED_PIN);
1341
        PROGLED_PORT        |=        (1<<PROGLED_PIN);        // active high LED ON
1342

    
1343
        while (!Serial_Available())
1344
        {
1345
                PROGLED_PORT        &=        ~(1<<PROGLED_PIN);        // turn LED off
1346
                delay_ms(100);
1347
                PROGLED_PORT        |=        (1<<PROGLED_PIN);        // turn LED on
1348
                delay_ms(100);
1349
        }
1350
        recchar();        //        get the char out of the buffer
1351
}
1352

    
1353
enum
1354
{
1355
        kDUMP_FLASH        =        0,
1356
        kDUMP_EEPROM,
1357
        kDUMP_RAM
1358
};
1359

    
1360
//************************************************************************
1361
static void        DumpHex(unsigned char dumpWhat, unsigned long startAddress, unsigned char numRows)
1362
{
1363
unsigned long        myAddressPointer;
1364
uint8_t                        ii;
1365
unsigned char        theValue;
1366
char                        asciiDump[18];
1367
unsigned char        *ramPtr;
1368

    
1369

    
1370
        ramPtr                                =        0;
1371
        theValue                        =        0;
1372
        myAddressPointer        =        startAddress;
1373
        while (numRows > 0)
1374
        {
1375
                if (myAddressPointer > 0x10000)
1376
                {
1377
                        PrintHexByte((myAddressPointer >> 16) & 0x00ff);
1378
                }
1379
                PrintHexByte((myAddressPointer >> 8) & 0x00ff);
1380
                PrintHexByte(myAddressPointer & 0x00ff);
1381
                sendchar(0x20);
1382
                sendchar('-');
1383
                sendchar(0x20);
1384

    
1385
                asciiDump[0]                =        0;
1386
                for (ii=0; ii<16; ii++)
1387
                {
1388
                        switch(dumpWhat)
1389
                        {
1390
                                case kDUMP_FLASH:
1391
                                        theValue        =        pgm_read_byte_far(myAddressPointer);
1392
                                        break;
1393

    
1394
                                case kDUMP_EEPROM:
1395
                                        theValue        =        eeprom_read_byte((void *)myAddressPointer);
1396
                                        break;
1397

    
1398
                                case kDUMP_RAM:
1399
                                        theValue        =        ramPtr[myAddressPointer];
1400
                                        break;
1401

    
1402
                        }
1403
                        PrintHexByte(theValue);
1404
                        sendchar(0x20);
1405
                        if ((theValue >= 0x20) && (theValue < 0x7f))
1406
                        {
1407
                                asciiDump[ii % 16]        =        theValue;
1408
                        }
1409
                        else
1410
                        {
1411
                                asciiDump[ii % 16]        =        '.';
1412
                        }
1413

    
1414
                        myAddressPointer++;
1415
                }
1416
                asciiDump[16]        =        0;
1417
                PrintString(asciiDump);
1418
                PrintNewLine();
1419

    
1420
                numRows--;
1421
        }
1422
}
1423

    
1424

    
1425

    
1426
//************************************************************************
1427
//*        returns amount of extended memory
1428
static void        EEPROMtest(void)
1429
{
1430
int                ii;
1431
char        theChar;
1432
char        theEEPROMchar;
1433
int                errorCount;
1434

    
1435
        PrintFromPROGMEMln(gTextMsg_WriteToEEprom, 0);
1436
        PrintNewLine();
1437
        ii                        =        0;
1438
        while (((theChar = pgm_read_byte_far(gTextMsg_Explorer + ii)) != '*') && (ii < 512))
1439
        {
1440
                eeprom_write_byte((uint8_t *)ii, theChar);
1441
                if (theChar == 0)
1442
                {
1443
                        PrintFromPROGMEM(gTextMsg_SPACE, 0);
1444
                }
1445
                else
1446
                {
1447
                        sendchar(theChar);
1448
                }
1449
                ii++;
1450
        }
1451

    
1452
        //*        no go back through and test
1453
        PrintNewLine();
1454
        PrintNewLine();
1455
        PrintFromPROGMEMln(gTextMsg_ReadingEEprom, 0);
1456
        PrintNewLine();
1457
        errorCount        =        0;
1458
        ii                        =        0;
1459
        while (((theChar = pgm_read_byte_far(gTextMsg_Explorer + ii)) != '*') && (ii < 512))
1460
        {
1461
                theEEPROMchar        =        eeprom_read_byte((uint8_t *)ii);
1462
                if (theEEPROMchar == 0)
1463
                {
1464
                        PrintFromPROGMEM(gTextMsg_SPACE, 0);
1465
                }
1466
                else
1467
                {
1468
                        sendchar(theEEPROMchar);
1469
                }
1470
                if (theEEPROMchar != theChar)
1471
                {
1472
                        errorCount++;
1473
                }
1474
                ii++;
1475
        }
1476
        PrintNewLine();
1477
        PrintNewLine();
1478
        PrintFromPROGMEM(gTextMsg_EEPROMerrorCnt, 0);
1479
        PrintDecInt(errorCount, 1);
1480
        PrintNewLine();
1481
        PrintNewLine();
1482

    
1483
        gEepromIndex        =        0;        //*        set index back to zero for next eeprom dump
1484

    
1485
}
1486

    
1487

    
1488

    
1489
#if (FLASHEND > 0x08000)
1490
        #include        "avrinterruptnames.h"
1491
        #ifndef _INTERRUPT_NAMES_DEFINED_
1492
                #warning Interrupt vectors not defined
1493
        #endif
1494
#endif
1495

    
1496
//************************************************************************
1497
static void        VectorDisplay(void)
1498
{
1499
unsigned long        byte1;
1500
unsigned long        byte2;
1501
unsigned long        byte3;
1502
unsigned long        byte4;
1503
unsigned long        word1;
1504
unsigned long        word2;
1505
int                                vectorIndex;
1506
unsigned long        myMemoryPtr;
1507
unsigned long        wordMemoryAddress;
1508
unsigned long        realitiveAddr;
1509
unsigned long        myFullAddress;
1510
unsigned long        absoluteAddr;
1511
#if defined(_INTERRUPT_NAMES_DEFINED_)
1512
        long                stringPointer;
1513
#endif
1514

    
1515
        myMemoryPtr                =        0;
1516
        vectorIndex                =        0;
1517
        PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
1518
        PrintFromPROGMEMln(gTextMsg_VECTOR_HEADER, 0);
1519
        //                                         V#   ADDR   op code
1520
        //                                          1 - 0000 = C3 BB 00 00 rjmp 03BB >000776 RESET
1521
        while (vectorIndex < kInterruptVectorCount)
1522
        {
1523
                wordMemoryAddress        =        myMemoryPtr / 2;
1524
                //                                         01 - 0000 = 12 34
1525
                PrintDecInt(vectorIndex + 1, 2);
1526
                sendchar(0x20);
1527
                sendchar('-');
1528
                sendchar(0x20);
1529
                PrintHexByte((wordMemoryAddress >> 8) & 0x00ff);
1530
                PrintHexByte((wordMemoryAddress) & 0x00ff);
1531
                sendchar(0x20);
1532
                sendchar('=');
1533
                sendchar(0x20);
1534

    
1535
        
1536
                //*        the AVR is LITTLE ENDIAN, swap the byte order
1537
                byte1        =        pgm_read_byte_far(myMemoryPtr++);
1538
                byte2        =        pgm_read_byte_far(myMemoryPtr++);
1539
                word1        =        (byte2 << 8) + byte1;
1540

    
1541
                byte3        =        pgm_read_byte_far(myMemoryPtr++);
1542
                byte4        =        pgm_read_byte_far(myMemoryPtr++);
1543
                word2        =        (byte4 << 8) + byte3;
1544

    
1545

    
1546
                PrintHexByte(byte2);
1547
                sendchar(0x20);
1548
                PrintHexByte(byte1);
1549
                sendchar(0x20);
1550
                PrintHexByte(byte4);
1551
                sendchar(0x20);
1552
                PrintHexByte(byte3);
1553
                sendchar(0x20);
1554
        
1555
                if (word1 == 0xffff)
1556
                {
1557
                        PrintFromPROGMEM(gTextMsg_noVector, 0);
1558
                }
1559
                else if ((word1 & 0xc000) == 0xc000)
1560
                {
1561
                        //*        rjmp instruction
1562
                        realitiveAddr        =        word1 & 0x3FFF;
1563
                        absoluteAddr        =        wordMemoryAddress + realitiveAddr;        //*        add the offset to the current address
1564
                        absoluteAddr        =        absoluteAddr << 1;                                        //*        multiply by 2 for byte address
1565

    
1566
                        PrintFromPROGMEM(gTextMsg_rjmp, 0);
1567
                        PrintHexByte((realitiveAddr >> 8) & 0x00ff);
1568
                        PrintHexByte((realitiveAddr) & 0x00ff);
1569
                        sendchar(0x20);
1570
                        sendchar('>');
1571
                        PrintHexByte((absoluteAddr >> 16) & 0x00ff);
1572
                        PrintHexByte((absoluteAddr >> 8) & 0x00ff);
1573
                        PrintHexByte((absoluteAddr) & 0x00ff);
1574
        
1575
                }
1576
                else if ((word1 & 0xfE0E) == 0x940c)
1577
                {
1578
                        //*        jmp instruction, this is REALLY complicated, refer to the instruction manual (JMP)
1579
                        myFullAddress        =        ((byte1 & 0x01) << 16) +
1580
                                                                ((byte1 & 0xf0) << 17) +
1581
                                                                ((byte2 & 0x01) << 21) +
1582
                                                                word2;
1583
                                                        
1584
                        absoluteAddr        =        myFullAddress << 1;
1585
                                                        
1586
                        PrintFromPROGMEM(gTextMsg_jmp, 0);
1587
                        PrintHexByte((myFullAddress >> 16) & 0x00ff);
1588
                        PrintHexByte((myFullAddress >> 8) & 0x00ff);
1589
                        PrintHexByte((myFullAddress) & 0x00ff);
1590
                        sendchar(0x20);
1591
                        sendchar('>');
1592
                        PrintHexByte((absoluteAddr >> 16) & 0x00ff);
1593
                        PrintHexByte((absoluteAddr >> 8) & 0x00ff);
1594
                        PrintHexByte((absoluteAddr) & 0x00ff);
1595
                }
1596

    
1597
        #if defined(_INTERRUPT_NAMES_DEFINED_)
1598
                sendchar(0x20);
1599
                stringPointer        =        pgm_read_word_far(&(gInterruptNameTable[vectorIndex]));
1600
                PrintFromPROGMEM((char *)stringPointer, 0);
1601
        #endif
1602
                PrintNewLine();
1603

    
1604
                vectorIndex++;
1605
        }
1606
}
1607

    
1608
//************************************************************************
1609
static void        PrintAvailablePort(char thePortLetter)
1610
{
1611
        PrintFromPROGMEM(gTextMsg_PORT, 0);
1612
        sendchar(thePortLetter);
1613
        PrintNewLine();
1614
}
1615

    
1616
//************************************************************************
1617
static void        ListAvailablePorts(void)
1618
{
1619

    
1620
#ifdef DDRA
1621
        PrintAvailablePort('A');
1622
#endif
1623

    
1624
#ifdef DDRB
1625
        PrintAvailablePort('B');
1626
#endif
1627

    
1628
#ifdef DDRC
1629
        PrintAvailablePort('C');
1630
#endif
1631

    
1632
#ifdef DDRD
1633
        PrintAvailablePort('D');
1634
#endif
1635

    
1636
#ifdef DDRE
1637
        PrintAvailablePort('E');
1638
#endif
1639

    
1640
#ifdef DDRF
1641
        PrintAvailablePort('F');
1642
#endif
1643

    
1644
#ifdef DDRG
1645
        PrintAvailablePort('G');
1646
#endif
1647

    
1648
#ifdef DDRH
1649
        PrintAvailablePort('H');
1650
#endif
1651

    
1652
#ifdef DDRI
1653
        PrintAvailablePort('I');
1654
#endif
1655

    
1656
#ifdef DDRJ
1657
        PrintAvailablePort('J');
1658
#endif
1659

    
1660
#ifdef DDRK
1661
        PrintAvailablePort('K');
1662
#endif
1663

    
1664
#ifdef DDRL
1665
        PrintAvailablePort('L');
1666
#endif
1667

    
1668
}
1669

    
1670
//************************************************************************
1671
static void        AVR_PortOutput(void)
1672
{
1673
char        portLetter;
1674
char        getCharFlag;
1675

    
1676
        PrintFromPROGMEM(gTextMsg_WHAT_PORT, 0);
1677

    
1678
        portLetter        =        recchar();
1679
        portLetter        =        portLetter & 0x5f;
1680
        sendchar(portLetter);
1681
        PrintNewLine();
1682

    
1683
        if ((portLetter >= 'A') && (portLetter <= 'Z'))
1684
        {
1685
                getCharFlag        =        true;
1686
                switch(portLetter)
1687
                {
1688
                #ifdef DDRA
1689
                        case 'A':
1690
                                DDRA        =        0xff;
1691
                                while (!Serial_Available())
1692
                                {
1693
                                        PORTA        ^=        0xff;
1694
                                        delay_ms(200);
1695
                                }
1696
                                PORTA        =        0;
1697
                                break;
1698
                #endif
1699

    
1700
                #ifdef DDRB
1701
                        case 'B':
1702
                                DDRB        =        0xff;
1703
                                while (!Serial_Available())
1704
                                {
1705
                                        PORTB        ^=        0xff;
1706
                                        delay_ms(200);
1707
                                }
1708
                                PORTB        =        0;
1709
                                break;
1710
                #endif
1711

    
1712
                #ifdef DDRC
1713
                        case 'C':
1714
                                DDRC        =        0xff;
1715
                                while (!Serial_Available())
1716
                                {
1717
                                        PORTC        ^=        0xff;
1718
                                        delay_ms(200);
1719
                                }
1720
                                PORTC        =        0;
1721
                                break;
1722
                #endif
1723

    
1724
                #ifdef DDRD
1725
                        case 'D':
1726
                                DDRD        =        0xff;
1727
                                while (!Serial_Available())
1728
                                {
1729
                                        PORTD        ^=        0xff;
1730
                                        delay_ms(200);
1731
                                }
1732
                                PORTD        =        0;
1733
                                break;
1734
                #endif
1735

    
1736
                #ifdef DDRE
1737
                        case 'E':
1738
                                DDRE        =        0xff;
1739
                                while (!Serial_Available())
1740
                                {
1741
                                        PORTE        ^=        0xff;
1742
                                        delay_ms(200);
1743
                                }
1744
                                PORTE        =        0;
1745
                                break;
1746
                #endif
1747

    
1748
                #ifdef DDRF
1749
                        case 'F':
1750
                                DDRF        =        0xff;
1751
                                while (!Serial_Available())
1752
                                {
1753
                                        PORTF        ^=        0xff;
1754
                                        delay_ms(200);
1755
                                }
1756
                                PORTF        =        0;
1757
                                break;
1758
                #endif
1759

    
1760
                #ifdef DDRG
1761
                        case 'G':
1762
                                DDRG        =        0xff;
1763
                                while (!Serial_Available())
1764
                                {
1765
                                        PORTG        ^=        0xff;
1766
                                        delay_ms(200);
1767
                                }
1768
                                PORTG        =        0;
1769
                                break;
1770
                #endif
1771

    
1772
                #ifdef DDRH
1773
                        case 'H':
1774
                                DDRH        =        0xff;
1775
                                while (!Serial_Available())
1776
                                {
1777
                                        PORTH        ^=        0xff;
1778
                                        delay_ms(200);
1779
                                }
1780
                                PORTH        =        0;
1781
                                break;
1782
                #endif
1783

    
1784
                #ifdef DDRI
1785
                        case 'I':
1786
                                DDRI        =        0xff;
1787
                                while (!Serial_Available())
1788
                                {
1789
                                        PORTI        ^=        0xff;
1790
                                        delay_ms(200);
1791
                                }
1792
                                PORTI        =        0;
1793
                                break;
1794
                #endif
1795

    
1796
                #ifdef DDRJ
1797
                        case 'J':
1798
                                DDRJ        =        0xff;
1799
                                while (!Serial_Available())
1800
                                {
1801
                                        PORTJ        ^=        0xff;
1802
                                        delay_ms(200);
1803
                                }
1804
                                PORTJ        =        0;
1805
                                break;
1806
                #endif
1807

    
1808
                #ifdef DDRK
1809
                        case 'K':
1810
                                DDRK        =        0xff;
1811
                                while (!Serial_Available())
1812
                                {
1813
                                        PORTK        ^=        0xff;
1814
                                        delay_ms(200);
1815
                                }
1816
                                PORTK        =        0;
1817
                                break;
1818
                #endif
1819

    
1820
                #ifdef DDRL
1821
                        case 'L':
1822
                                DDRL        =        0xff;
1823
                                while (!Serial_Available())
1824
                                {
1825
                                        PORTL        ^=        0xff;
1826
                                        delay_ms(200);
1827
                                }
1828
                                PORTL        =        0;
1829
                                break;
1830
                #endif
1831

    
1832
                        default:
1833
                                PrintFromPROGMEMln(gTextMsg_PortNotSupported, 0);
1834
                                getCharFlag        =        false;
1835
                                break;
1836
                }
1837
                if (getCharFlag)
1838
                {
1839
                        recchar();
1840
                }
1841
        }
1842
        else
1843
        {
1844
                PrintFromPROGMEMln(gTextMsg_MustBeLetter, 0);
1845
        }
1846
}
1847

    
1848

    
1849
//*******************************************************************
1850
static void PrintHelp(void)
1851
{
1852
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 0);
1853
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 0);
1854
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 0);
1855
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 0);
1856
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 0);
1857
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 0);
1858
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 0);
1859

    
1860
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 0);
1861
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 0);
1862
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 0);
1863
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 0);
1864
        PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 0);
1865
}
1866

    
1867
//************************************************************************
1868
static void        RunMonitor(void)
1869
{
1870
char                        keepGoing;
1871
unsigned char        theChar;
1872
int                                ii, jj;
1873

    
1874
        for (ii=0; ii<5; ii++)
1875
        {
1876
                for (jj=0; jj<25; jj++)
1877
                {
1878
                        sendchar('!');
1879
                }
1880
                PrintNewLine();
1881
        }
1882

    
1883
        gRamIndex                        =        0;
1884
        gFlashIndex                        =        0;
1885
        gEepromIndex                =        0;
1886

    
1887
        PrintFromPROGMEMln(gTextMsg_Explorer, 0);
1888

    
1889
        keepGoing        =        1;
1890
        while (keepGoing)
1891
        {
1892
                PrintFromPROGMEM(gTextMsg_Prompt, 0);
1893
                theChar        =        recchar();
1894
                if (theChar >= 0x60)
1895
                {
1896
                        theChar        =        theChar & 0x5F;
1897
                }
1898
        #if defined( _CEREBOTPLUS_BOARD_ )
1899
                if (theChar == 0x5F)
1900
                {
1901
                        
1902
                }
1903
                else
1904
        #endif
1905
                if (theChar >= 0x20)
1906
                {
1907
                        sendchar(theChar);
1908
                        sendchar(0x20);
1909
                }
1910

    
1911
                switch(theChar)
1912
                {
1913
                        case '0':
1914
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 2);
1915
                                gFlashIndex                =        0;
1916
                                gRamIndex                =        0;
1917
                                gEepromIndex        =        0;
1918
                                break;
1919

    
1920
                        case '?':
1921
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 2);
1922
                                PrintCPUstats();
1923
                                break;
1924

    
1925
                        case '@':
1926
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 2);
1927
                                EEPROMtest();
1928
                                break;
1929

    
1930
                        case 'B':
1931
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 2);
1932
                                BlinkLED();
1933
                                break;
1934

    
1935
                        case 'E':
1936
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 2);
1937
                                DumpHex(kDUMP_EEPROM, gEepromIndex, 16);
1938
                                gEepromIndex        +=        256;
1939
                                if (gEepromIndex > E2END)
1940
                                {
1941
                                        gEepromIndex        =        0;
1942
                                }
1943
                                break;
1944
                
1945
                        case 'F':
1946
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 2);
1947
                                DumpHex(kDUMP_FLASH, gFlashIndex, 16);
1948
                                gFlashIndex        +=        256;
1949
                                break;
1950

    
1951
                        case 'H':
1952
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 2);
1953
                                PrintHelp();
1954
                                break;
1955

    
1956
                        case 'L':
1957
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 2);
1958
                                ListAvailablePorts();
1959
                                break;
1960

    
1961
                        case 'Q':
1962
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 2);
1963
                                keepGoing        =        false;
1964
                                break;
1965

    
1966
                        case 'R':
1967
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 2);
1968
                                DumpHex(kDUMP_RAM, gRamIndex, 16);
1969
                                gRamIndex        +=        256;
1970
                                break;
1971

    
1972
                        case 'V':
1973
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 2);
1974
                                VectorDisplay();
1975
                                break;
1976

    
1977
                        case 'Y':
1978
                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 2);
1979
                                AVR_PortOutput();
1980
                                break;
1981
                        
1982
                #if defined( _CEREBOTPLUS_BOARD_ )
1983
                        case 0x5F:
1984
                                //*        do nothing
1985
                                break;
1986
                 #endif
1987
                 
1988
                        default:
1989
                                PrintFromPROGMEMln(gTextMsg_HUH, 0);
1990
                                break;
1991
                }
1992
        }
1993
}
1994

    
1995
#endif
1996