diff --git a/Makefile b/Makefile index da4ba93..1f830a8 100644 --- a/Makefile +++ b/Makefile @@ -48,4 +48,4 @@ bin: $(PRG).bin install: text # uisp -dprog=stk200 --erase --upload if=$(PRG).hex --verify - avrdude -p m16 -c butterfly -b 19200 -U flash:w:$(PRG).hex + avrdude -p m16 -c butterfly -b 19200 -P /dev/ttyUSB0 -U flash:w:$(PRG).hex diff --git a/ispprog.c b/ispprog.c index 0416f79..81981d1 100644 --- a/ispprog.c +++ b/ispprog.c @@ -1,59 +1,129 @@ -/* - * C based avr910 / avr109 ISP Adapter - * - * (c) 2006-2008 by Olaf Rempel - * - * - * using ATmega16 @7.3728MHz: - * PB1 = /Reset (to target) - * PB3 = /LED - * PB5 = MOSI (to target) - * PB6 = MISO (to target) - * PB7 = SCK (to target) - * PD3 = reset-in - * - */ +/*************************************************************************** + * C based avr910 / avr109 ISP Adapter * + * * + * Copyright (C) 2006 - 20011 by Olaf Rempel * + * razzor AT kopf MINUS tisch DOT de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License, * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ #include +#include #include +#include + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) + +/* + * using ATmega16 @7.3728MHz: + * Fuse H: 0xDA (512 words bootloader, jtag disabled) + * Fuse L: 0xFF (ext. Crystal) + */ #define F_CPU 7372800 #define BAUDRATE 115200 +#define TIMER_RELOAD (0xFF - 72) /* 10ms @7.3728MHz */ -/* SPI Clock: F_CPU /4 (1.8432MHz) or /128 (57.6kHz) */ -#define SPI_MODE ((1< #define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1) -#define LED_OFF 0x00 -#define LED_ON 0x01 -#define LED_FAST 0x02 -#define LED_SLOW 0x03 +/* F_CPU /4 (1.8432MHz) */ +#define SPI_MODE4 ((1< CMD_READ_FLASH */ - cmd = (lastcmd & 0x08) | 0x20; + cmd = (last_cmd & 0x08) | 0x20; } /* poll until we get correct value */ do { - val = mem_read(cmd, lastaddr); - } while ((val != lastval) && poll--); + val = mem_read(cmd, last_addr); + } while ((val != last_val) && poll--); } -int main(void) + +static void mem_pagewrite(uint16_t addr) +{ + spi_rxtx(CMD_WRITE_FLASH_PAGE); + spi_rxtx(addr >> 8); + spi_rxtx(addr & 0xFF); + spi_rxtx(0x00); + + poll(); +} + +static void cmdloop(void) { static uint8_t page_buf[256]; uint16_t addr = 0; - uint8_t device = 0, pagemask = 0; - - /* ISP_RESET and ISP_LED are outputs, pullup SlaveSelect */ - PORTB = (1<>8) & 0xFF; - UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); - - /* enable usart with 8n1 */ - UCSRB = (1<> 8); - spi_rxtx(lastaddr & 0xFF); - spi_rxtx(0x00); - - poll(); - + led_mode = LED_FAST; + mem_pagewrite(last_addr); ser_send('\r'); break; @@ -360,7 +373,7 @@ int main(void) /* Read program memory */ case 'R': - led_mode(LED_SLOW); + led_mode = LED_SLOW; ser_send(mem_read(CMD_READ_FLASH_HI, addr)); ser_send(mem_read(CMD_READ_FLASH_LO, addr)); addr++; @@ -368,14 +381,14 @@ int main(void) /* Read data memory */ case 'd': - led_mode(LED_SLOW); + led_mode = LED_SLOW; ser_send(mem_read(CMD_READ_EEPROM, addr)); addr++; break; /* Write data memory */ case 'D': - led_mode(LED_FAST); + led_mode = LED_FAST; mem_write(CMD_WRITE_EEPROM, addr, ser_recv()); poll(); @@ -390,7 +403,7 @@ int main(void) spi_rxtx(0x00); spi_rxtx(0x00); - _delay_ms(25); + _delay_ms(10); ser_send('\r'); break; @@ -402,7 +415,7 @@ int main(void) spi_rxtx(0x00); spi_rxtx(val); - _delay_ms(25); + _delay_ms(10); ser_send('\r'); break; } @@ -428,25 +441,13 @@ int main(void) /* Exit Bootloader */ case 'E': set_reset(1); - led_mode(LED_OFF); + led_mode = LED_OFF; ser_send('\r'); break; /* Select device type */ case 'T': { - uint8_t val, i = 0; - val = ser_recv(); - - do { - if (val == devices[i].id) { - device = val; - pagemask = devices[i].pagemask; - pollcode = devices[i].pollcode; - break; - } - - } while (devices[i++].id); - + ser_recv(); // ignore ser_send('\r'); break; } @@ -455,18 +456,17 @@ int main(void) case 's': { uint8_t i = 2; do { - ser_send(mem_read(CMD_READ_SIG_1, (CMD_READ_SIG_2 << 8) | i)); + ser_send(device.sig[i]); } while (i--); break; } /* Return supported device codes */ case 't': { - uint8_t val, i = 0; - do { - val = devices[i++].id; - ser_send(val); - } while (val); + uint8_t i; + for (i = 0; i < ARRAY_SIZE(devcodes); i++) { + ser_send(pgm_read_byte(&devcodes[i])); + } break; } @@ -501,28 +501,29 @@ int main(void) /* Set LED */ case 'x': ser_recv(); - led_mode(LED_ON); + led_mode = LED_ON; break; /* Clear LED */ case 'y': ser_recv(); - led_mode(LED_OFF); + led_mode = LED_OFF; break; /* Report Block write Mode */ - case 'b': + case 'b': { ser_send('Y'); ser_send(sizeof(page_buf) >> 8); ser_send(sizeof(page_buf) & 0xFF); break; + } /* Block Write */ case 'B': { uint16_t size, i; uint8_t type; - led_mode(LED_FAST); + led_mode = LED_FAST; size = ser_recv() << 8; size |= ser_recv(); @@ -538,25 +539,13 @@ int main(void) addr++; - /* page write on page-boundry */ - if ((addr & pagemask) == 0x00) { - spi_rxtx(CMD_WRITE_FLASH_PAGE); - spi_rxtx(lastaddr >> 8); - spi_rxtx(lastaddr & 0xFF); - spi_rxtx(0x00); - - poll(); + if ((addr & device.pagemask) == 0x00) { + mem_pagewrite(last_addr); } } - /* last page */ if (size != sizeof(page_buf)) { - spi_rxtx(CMD_WRITE_FLASH_PAGE); - spi_rxtx(lastaddr >> 8); - spi_rxtx(lastaddr & 0xFF); - spi_rxtx(0x00); - - poll(); + mem_pagewrite(last_addr); } } else if (type == 'E') { @@ -575,7 +564,7 @@ int main(void) uint16_t size, i; uint8_t type; - led_mode(LED_SLOW); + led_mode = LED_SLOW; size = ser_recv() << 8; size |= ser_recv(); @@ -605,7 +594,7 @@ int main(void) spi_rxtx(0x00); spi_rxtx(val); - _delay_ms(25); + _delay_ms(10); ser_send('\r'); break; } @@ -621,7 +610,7 @@ int main(void) spi_rxtx(val[1]); ser_send(spi_rxtx(val[2])); - _delay_ms(25); + _delay_ms(10); ser_send('\r'); break; } @@ -639,7 +628,7 @@ int main(void) spi_rxtx(val[2]); ser_send(spi_rxtx(val[3])); - _delay_ms(25); + _delay_ms(10); ser_send('\r'); break; } @@ -653,5 +642,219 @@ int main(void) break; } } +} + +static uint16_t statemachine(uint8_t event) +{ + static uint8_t oldstate; + uint8_t state = oldstate; + uint16_t timer; + + do { + if (state != oldstate) { + event = EV_STATE_ENTER; + } + + switch (state) { + case STATE_IDLE: + if (event == EV_STATE_ENTER) { + led_mode = LED_OFF; + timer = 0xFFFF; /* stop timer */ + + } else if (event == EV_BUTTON_PRESSED) { + state = STATE_PRESSED; + set_reset(0); + } + break; + + case STATE_PRESSED: + if (event == EV_STATE_ENTER) { + led_mode = LED_ON; + timer = 5; /* timeout 50ms (== reset length) */ + + } else if (event == EV_BUTTON_RELEASED) { + state = STATE_IDLE; + set_reset(1); + + } else if (event == EV_TIMEOUT) { + state = STATE_PRESSED2; + set_reset(1); + } + break; + + case STATE_PRESSED2: + if (event == EV_STATE_ENTER) { + led_mode = LED_OFF; + timer = 500; /* timeout in 5s */ + + } else if (event == EV_BUTTON_RELEASED) { + state = STATE_IDLE; + + } else if (event == EV_TIMEOUT) { + switch (SPCR) { + case SPI_MODE1: + state = STATE_SPEED1; + break; + + case SPI_MODE2: + state = STATE_SPEED2; + break; + + case SPI_MODE3: + state = STATE_SPEED3; + break; + + default: + case SPI_MODE4: + state = STATE_SPEED4; + break; + } + } + break; + + case STATE_SPEED1: + if (event == EV_STATE_ENTER) { + led_mode = LED_SPEED1; + timer = 500; /* timeout in 5s */ + + } else if (event == EV_BUTTON_PRESSED) { + state = STATE_SPEED2; + + } else if (event == EV_TIMEOUT) { + state = STATE_IDLE; + SPCR = SPI_MODE1; + } + break; + + case STATE_SPEED2: + if (event == EV_STATE_ENTER) { + led_mode = LED_SPEED2; + timer = 500; /* timeout in 5s */ + + } else if (event == EV_BUTTON_PRESSED) { + state = STATE_SPEED3; + + } else if (event == EV_TIMEOUT) { + state = STATE_IDLE; + SPCR = SPI_MODE2; + } + break; + + case STATE_SPEED3: + if (event == EV_STATE_ENTER) { + led_mode = LED_SPEED3; + timer = 500; /* timeout in 5s */ + + } else if (event == EV_BUTTON_PRESSED) { + state = STATE_SPEED4; + + } else if (event == EV_TIMEOUT) { + state = STATE_IDLE; + SPCR = SPI_MODE3; + } + break; + + case STATE_SPEED4: + if (event == EV_STATE_ENTER) { + led_mode = LED_SPEED4; + timer = 500; /* timeout in 5s */ + + } else if (event == EV_BUTTON_PRESSED) { + state = STATE_SPEED1; + + } else if (event == EV_TIMEOUT) { + state = STATE_IDLE; + SPCR = SPI_MODE4; + } + break; + + default: + state = STATE_IDLE; + break; + } + + if (event == EV_STATE_ENTER) { + oldstate = state; + } + + } while (state != oldstate); + + return timer; +} + +/* time keeping */ +ISR(TIMER0_OVF_vect) +{ + uint8_t event = EV_NONE; + + /* restart timer */ + TCNT0 = TIMER_RELOAD; + + static uint8_t prev_pressed; + if (PIND & (1< 0) { + timer = new_timer; + } + } + + /* update LED */ + static uint8_t led_timer; + + if (led_mode & ((led_timer++ & 0xFF) | 0x80)) { + PORTB &= ~(1<>8) & 0xFF; + UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); + + /* enable usart with 8n1 */ + UCSRB = (1<