diff --git a/libraries/ESP8266AVRISP/README.md b/libraries/ESP8266AVRISP/README.md new file mode 100644 index 000000000..be691aaa8 --- /dev/null +++ b/libraries/ESP8266AVRISP/README.md @@ -0,0 +1,57 @@ +# AVR In-System Programming over WiFi for ESP8266 + +This library allows an ESP8266 module with the HSPI port available to become +an AVR In-System Programmer. + +## Hardware + +The ESP8266 module connects to the AVR target chip via the standard 6-pin +AVR "Recommended In-System Programming Interface Connector Layout" as seen +in [AVR910](http://www.atmel.com/images/doc0943.pdf) among other places. + +If the AVR target is powered by a different Vcc than what powers your ESP8266 +chip, you **must provide voltage level shifting** or some other form of buffers. +Exposing the pins of ESP8266 to anything larger than 3.6V will damage it. + +Connections are as follows: + +ESP8266 | AVR / SPI +--------|------------ +GPIO12 | MISO +GPIO13 | MOSI +GPIO14 | SCK +any* | RESET + +For RESET use a GPIO other than 0, 2 and 15 (bootselect pins), and apply an +external pullup/down so that the target is normally running. + +## Usage + +See the included example. In short: + +```arduino + +// Create the programmer object +ESP8266AVRISP avrprog(PORT, RESET_PIN) +// ... with custom SPI frequency +ESP8266AVRISP avrprog(PORT, RESET_PIN, 4e6) + +// Check current connection state, but don't perform any actions +AVRISPState_t state = avrprog.update(); + +// Serve the pending connection, execute STK500 commands +AVRISPState_t state = avrprog.serve(); +``` + +### License and Authors + +This library started off from the source of ArduinoISP "sketch" included with +the Arduino IDE: + + ArduinoISP version 04m3 + Copyright (c) 2008-2011 Randall Bohn + If you require a license, see + http://www.opensource.org/licenses/bsd-license.php + + Support for TCP on ESP8266 + Copyright (c) Kiril Zyapkov . diff --git a/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino b/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino new file mode 100644 index 000000000..792d702c9 --- /dev/null +++ b/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +const char* host = "esp8266-avrisp"; +const char* ssid = "**********"; +const char* pass = "**********"; +const uint16_t port = 328; +const uint8_t reset_pin = 5; + +ESP8266AVRISP avrprog(port, reset_pin); + +void setup() { + Serial.begin(115200); + Serial.println(""); + Serial.println("Arduino AVR-ISP over TCP"); + avrprog.setReset(false); // let the AVR run + + WiFi.begin(ssid, pass); + while (WiFi.waitForConnectResult() != WL_CONNECTED); + + MDNS.begin(host); + MDNS.addService("avrisp", "tcp", port); + + IPAddress local_ip = WiFi.localIP(); + Serial.print("IP address: "); + Serial.println(local_ip); + Serial.println("Use your avrdude:"); + Serial.print("avrdude -c arduino -p -P net:"); + Serial.print(local_ip); + Serial.print(":"); + Serial.print(port); + Serial.println(" -t # or -U ..."); + + // listen for avrdudes + avrprog.begin(); +} + +void loop() { + static AVRISPState_t last_state = AVRISP_STATE_IDLE; + AVRISPState_t new_state = avrprog.update(); + if (last_state != new_state) { + switch (new_state) { + case AVRISP_STATE_IDLE: { + Serial.printf("[AVRISP] now idle\r\n"); + // Use the SPI bus for other purposes + break; + } + case AVRISP_STATE_PENDING: { + Serial.printf("[AVRISP] connection pending\r\n"); + // Clean up your other purposes and prepare for programming mode + break; + } + case AVRISP_STATE_ACTIVE: { + Serial.printf("[AVRISP] programming mode\r\n"); + // Stand by for completion + break; + } + } + last_state = new_state; + } + // Serve the client + if (last_state != AVRISP_STATE_IDLE) { + avrprog.serve(); + } +} diff --git a/libraries/ESP8266AVRISP/library.properties b/libraries/ESP8266AVRISP/library.properties new file mode 100644 index 000000000..70fa3cf8e --- /dev/null +++ b/libraries/ESP8266AVRISP/library.properties @@ -0,0 +1,9 @@ +name=ESP8266AVRISP +version=1.0 +author=Kiril Zyapkov +maintainer=Kiril Zyapkov +sentence=AVR In-System Programming over WiFi for ESP8266 +paragraph=This library allows programming 8-bit AVR ICSP targets via TCP over WiFi with ESP8266. +category=Communication +url= +architectures=esp8266 diff --git a/libraries/ESP8266AVRISP/src/ESP8266AVRISP.cpp b/libraries/ESP8266AVRISP/src/ESP8266AVRISP.cpp new file mode 100644 index 000000000..1cdeb26e8 --- /dev/null +++ b/libraries/ESP8266AVRISP/src/ESP8266AVRISP.cpp @@ -0,0 +1,541 @@ +/* +AVR In-System Programming over WiFi for ESP8266 +Copyright (c) Kiril Zyapkov + +Original version: + ArduinoISP version 04m3 + Copyright (c) 2008-2011 Randall Bohn + If you require a license, see + http://www.opensource.org/licenses/bsd-license.php +*/ + + +#include +#include +#include +#include + +#include "ESP8266AVRISP.h" +#include "command.h" + +extern "C" { + #include "user_interface.h" + #include "mem.h" +} + +#define malloc os_malloc +#define free os_free + +#ifdef AVRISP_ACTIVE_HIGH_RESET +#define AVRISP_RESET_ON HIGH +#define AVRISP_RESET_OFF LOW +#else +#define AVRISP_RESET_ON LOW +#define AVRISP_RESET_OFF HIGH +#endif + + +// #define AVRISP_DEBUG(fmt, ...) os_printf("[AVRP] " fmt "\r\n", ##__VA_ARGS__ ) +#define AVRISP_DEBUG(...) + +#define AVRISP_HWVER 2 +#define AVRISP_SWMAJ 1 +#define AVRISP_SWMIN 18 +#define AVRISP_PTIME 10 + +#define EECHUNK (32) + +#define beget16(addr) (*addr * 256 + *(addr+1)) + +ESP8266AVRISP::ESP8266AVRISP(uint16_t port, uint8_t reset_pin, uint32_t spi_freq, bool reset_state): + _reset_pin(reset_pin), _reset_state(reset_state), _spi_freq(spi_freq), + _server(WiFiServer(port)), _state(AVRISP_STATE_IDLE) +{ + pinMode(_reset_pin, OUTPUT); + setReset(_reset_state); +} + +void ESP8266AVRISP::begin() { + _server.begin(); +} + +void ESP8266AVRISP::setSpiFrequency(uint32_t freq) { + _spi_freq = freq; + if (_state == AVRISP_STATE_ACTIVE) { + SPI.setFrequency(freq); + } +} + +void ESP8266AVRISP::setReset(bool rst) { + _reset_state = rst; + if (_reset_state) { + digitalWrite(_reset_pin, AVRISP_RESET_ON); + } else { + digitalWrite(_reset_pin, AVRISP_RESET_OFF); + } +} + +AVRISPState_t ESP8266AVRISP::update() { + switch (_state) { + case AVRISP_STATE_IDLE: { + if (_server.hasClient()) { + _client = _server.available(); + _client.setNoDelay(true); + ip_addr_t lip; + lip.addr = _client.remoteIP(); + AVRISP_DEBUG("client connect %d.%d.%d.%d:%d", IP2STR(&lip), _client.remotePort()); + _client.setTimeout(100); // for getch() + _state = AVRISP_STATE_PENDING; + _reject_incoming(); + } + break; + } + case AVRISP_STATE_PENDING: + case AVRISP_STATE_ACTIVE: { + // handle disconnect + if (!_client.connected()) { + _client.stop(); + AVRISP_DEBUG("client disconnect"); + if (pmode) { + SPI.end(); + pmode = 0; + } + setReset(_reset_state); + _state = AVRISP_STATE_IDLE; + } else { + _reject_incoming(); + } + break; + } + } + return _state; +} + +AVRISPState_t ESP8266AVRISP::serve() { + switch (update()) { + case AVRISP_STATE_IDLE: + // should not be called when idle, error? + break; + case AVRISP_STATE_PENDING: { + _state = AVRISP_STATE_ACTIVE; + // fallthrough + } + case AVRISP_STATE_ACTIVE: { + while (_client.available()) { + avrisp(); + } + return update(); + } + } + return _state; +} + +inline void ESP8266AVRISP::_reject_incoming(void) { + while (_server.hasClient()) _server.available().stop(); +} + +uint8_t ESP8266AVRISP::getch() { + while (!_client.available()) yield(); + uint8_t b = (uint8_t)_client.read(); + // AVRISP_DEBUG("< %02x", b); + return b; +} + +void ESP8266AVRISP::fill(int n) { + // AVRISP_DEBUG("fill(%u)", n); + for (int x = 0; x < n; x++) { + buff[x] = getch(); + } +} + +uint8_t ESP8266AVRISP::spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + uint8_t n; + SPI.transfer(a); + n = SPI.transfer(b); + n = SPI.transfer(c); + return SPI.transfer(d); +} + +void ESP8266AVRISP::empty_reply() { + if (Sync_CRC_EOP == getch()) { + _client.print((char)Resp_STK_INSYNC); + _client.print((char)Resp_STK_OK); + } else { + error++; + _client.print((char)Resp_STK_NOSYNC); + } +} + +void ESP8266AVRISP::breply(uint8_t b) { + if (Sync_CRC_EOP == getch()) { + uint8_t resp[3]; + resp[0] = Resp_STK_INSYNC; + resp[1] = b; + resp[2] = Resp_STK_OK; + _client.write((const uint8_t *)resp, (size_t)3); + } else { + error++; + _client.print((char)Resp_STK_NOSYNC); + } + +} + +void ESP8266AVRISP::get_parameter(uint8_t c) { + switch (c) { + case 0x80: + breply(AVRISP_HWVER); + break; + case 0x81: + breply(AVRISP_SWMAJ); + break; + case 0x82: + breply(AVRISP_SWMIN); + break; + case 0x93: + breply('S'); // serial programmer + break; + default: + breply(0); + } +} + +void ESP8266AVRISP::set_parameters() { + // call this after reading paramter packet into buff[] + param.devicecode = buff[0]; + param.revision = buff[1]; + param.progtype = buff[2]; + param.parmode = buff[3]; + param.polling = buff[4]; + param.selftimed = buff[5]; + param.lockbytes = buff[6]; + param.fusebytes = buff[7]; + param.flashpoll = buff[8]; + // ignore buff[9] (= buff[8]) + // following are 16 bits (big endian) + param.eeprompoll = beget16(&buff[10]); + param.pagesize = beget16(&buff[12]); + param.eepromsize = beget16(&buff[14]); + + // 32 bits flashsize (big endian) + param.flashsize = buff[16] * 0x01000000 + + buff[17] * 0x00010000 + + buff[18] * 0x00000100 + + buff[19]; +} + +void ESP8266AVRISP::start_pmode() { + SPI.begin(); + SPI.setFrequency(_spi_freq); + SPI.setHwCs(false); + + // try to sync the bus + SPI.transfer(0x00); + digitalWrite(_reset_pin, AVRISP_RESET_OFF); + delayMicroseconds(50); + digitalWrite(_reset_pin, AVRISP_RESET_ON); + delay(30); + + spi_transaction(0xAC, 0x53, 0x00, 0x00); + pmode = 1; +} + +void ESP8266AVRISP::end_pmode() { + SPI.end(); + setReset(_reset_state); + pmode = 0; +} + +void ESP8266AVRISP::universal() { + int w; + uint8_t ch; + + fill(4); + ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]); + breply(ch); +} + +void ESP8266AVRISP::flash(uint8_t hilo, int addr, uint8_t data) { + spi_transaction(0x40 + 8 * hilo, + addr >> 8 & 0xFF, + addr & 0xFF, + data); +} + +void ESP8266AVRISP::commit(int addr) { + spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); + delay(AVRISP_PTIME); +} + +//#define _addr_page(x) (here & 0xFFFFE0) +int ESP8266AVRISP::addr_page(int addr) { + if (param.pagesize == 32) return addr & 0xFFFFFFF0; + if (param.pagesize == 64) return addr & 0xFFFFFFE0; + if (param.pagesize == 128) return addr & 0xFFFFFFC0; + if (param.pagesize == 256) return addr & 0xFFFFFF80; + AVRISP_DEBUG("unknown page size: %d", param.pagesize); + return addr; +} + + +void ESP8266AVRISP::write_flash(int length) { + uint32_t started = millis(); + + fill(length); + + if (Sync_CRC_EOP == getch()) { + _client.print((char) Resp_STK_INSYNC); + _client.print((char) write_flash_pages(length)); + } else { + error++; + _client.print((char) Resp_STK_NOSYNC); + } +} + +uint8_t ESP8266AVRISP::write_flash_pages(int length) { + int x = 0; + int page = addr_page(here); + while (x < length) { + yield(); + if (page != addr_page(here)) { + commit(page); + page = addr_page(here); + } + flash(LOW, here, buff[x++]); + flash(HIGH, here, buff[x++]); + here++; + } + commit(page); + return Resp_STK_OK; +} + +uint8_t ESP8266AVRISP::write_eeprom(int length) { + // here is a word address, get the byte address + int start = here * 2; + int remaining = length; + if (length > param.eepromsize) { + error++; + return Resp_STK_FAILED; + } + while (remaining > EECHUNK) { + write_eeprom_chunk(start, EECHUNK); + start += EECHUNK; + remaining -= EECHUNK; + } + write_eeprom_chunk(start, remaining); + return Resp_STK_OK; +} +// write (length) bytes, (start) is a byte address +uint8_t ESP8266AVRISP::write_eeprom_chunk(int start, int length) { + // this writes byte-by-byte, + // page writing may be faster (4 bytes at a time) + fill(length); + // prog_lamp(LOW); + for (int x = 0; x < length; x++) { + int addr = start + x; + spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]); + delay(45); + } + // prog_lamp(HIGH); + return Resp_STK_OK; +} + +void ESP8266AVRISP::program_page() { + char result = (char) Resp_STK_FAILED; + int length = 256 * getch(); + length += getch(); + char memtype = getch(); + char buf[100]; + // flash memory @here, (length) bytes + if (memtype == 'F') { + write_flash(length); + return; + } + + if (memtype == 'E') { + result = (char)write_eeprom(length); + if (Sync_CRC_EOP == getch()) { + _client.print((char) Resp_STK_INSYNC); + _client.print(result); + } else { + error++; + _client.print((char) Resp_STK_NOSYNC); + } + return; + } + _client.print((char)Resp_STK_FAILED); + return; + +} + +uint8_t ESP8266AVRISP::flash_read(uint8_t hilo, int addr) { + return spi_transaction(0x20 + hilo * 8, + (addr >> 8) & 0xFF, + addr & 0xFF, + 0); +} + +void ESP8266AVRISP::flash_read_page(int length) { + uint8_t *data = (uint8_t *) malloc(length + 1); + for (int x = 0; x < length; x += 2) { + *(data + x) = flash_read(LOW, here); + *(data + x + 1) = flash_read(HIGH, here); + here++; + } + *(data + length) = Resp_STK_OK; + _client.write((const uint8_t *)data, (size_t)(length + 1)); + free(data); + return; +} + +void ESP8266AVRISP::eeprom_read_page(int length) { + // here again we have a word address + uint8_t *data = (uint8_t *) malloc(length + 1); + int start = here * 2; + for (int x = 0; x < length; x++) { + int addr = start + x; + uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); + *(data + x) = ee; + } + *(data + length) = Resp_STK_OK; + _client.write((const uint8_t *)data, (size_t)(length + 1)); + free(data); + return; +} + +void ESP8266AVRISP::read_page() { + char result = (char)Resp_STK_FAILED; + int length = 256 * getch(); + length += getch(); + char memtype = getch(); + if (Sync_CRC_EOP != getch()) { + error++; + _client.print((char) Resp_STK_NOSYNC); + return; + } + _client.print((char) Resp_STK_INSYNC); + if (memtype == 'F') flash_read_page(length); + if (memtype == 'E') eeprom_read_page(length); + return; +} + +void ESP8266AVRISP::read_signature() { + if (Sync_CRC_EOP != getch()) { + error++; + _client.print((char) Resp_STK_NOSYNC); + return; + } + _client.print((char) Resp_STK_INSYNC); + + uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00); + _client.print((char) high); + uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00); + _client.print((char) middle); + uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00); + _client.print((char) low); + _client.print((char) Resp_STK_OK); +} + +// It seems ArduinoISP is based on the original STK500 (not v2) +// but implements only a subset of the commands. +int ESP8266AVRISP::avrisp() { + uint8_t data, low, high; + uint8_t ch = getch(); + // AVRISP_DEBUG("CMD 0x%02x", ch); + switch (ch) { + case Cmnd_STK_GET_SYNC: + error = 0; + empty_reply(); + break; + + case Cmnd_STK_GET_SIGN_ON: + if (getch() == Sync_CRC_EOP) { + _client.print((char) Resp_STK_INSYNC); + _client.print(F("AVR ISP")); // AVR061 says "AVR STK"? + _client.print((char) Resp_STK_OK); + } + break; + + case Cmnd_STK_GET_PARAMETER: + get_parameter(getch()); + break; + + case Cmnd_STK_SET_DEVICE: + fill(20); + set_parameters(); + empty_reply(); + break; + + case Cmnd_STK_SET_DEVICE_EXT: // ignored + fill(5); + empty_reply(); + break; + + case Cmnd_STK_ENTER_PROGMODE: + start_pmode(); + empty_reply(); + break; + + case Cmnd_STK_LOAD_ADDRESS: + here = getch(); + here += 256 * getch(); + // AVRISP_DEBUG("here=0x%04x", here); + empty_reply(); + break; + + // XXX: not implemented! + case Cmnd_STK_PROG_FLASH: + low = getch(); + high = getch(); + empty_reply(); + break; + + // XXX: not implemented! + case Cmnd_STK_PROG_DATA: + data = getch(); + empty_reply(); + break; + + case Cmnd_STK_PROG_PAGE: + program_page(); + break; + + case Cmnd_STK_READ_PAGE: + read_page(); + break; + + case Cmnd_STK_UNIVERSAL: + universal(); + break; + + case Cmnd_STK_LEAVE_PROGMODE: + error = 0; + end_pmode(); + empty_reply(); + delay(5); + // if (_client && _client.connected()) + _client.stop(); + // AVRISP_DEBUG("left progmode"); + + break; + + case Cmnd_STK_READ_SIGN: + read_signature(); + break; + // expecting a command, not Sync_CRC_EOP + // this is how we can get back in sync + case Sync_CRC_EOP: // 0x20, space + error++; + _client.print((char) Resp_STK_NOSYNC); + break; + + // anything else we will return STK_UNKNOWN + default: + AVRISP_DEBUG("??!?"); + error++; + if (Sync_CRC_EOP == getch()) { + _client.print((char)Resp_STK_UNKNOWN); + } else { + _client.print((char)Resp_STK_NOSYNC); + } + } +} diff --git a/libraries/ESP8266AVRISP/src/ESP8266AVRISP.h b/libraries/ESP8266AVRISP/src/ESP8266AVRISP.h new file mode 100644 index 000000000..d2bc6f1bc --- /dev/null +++ b/libraries/ESP8266AVRISP/src/ESP8266AVRISP.h @@ -0,0 +1,125 @@ +/* +AVR In-System Programming over WiFi for ESP8266 +Copyright (c) Kiril Zyapkov + +Original version: + ArduinoISP version 04m3 + Copyright (c) 2008-2011 Randall Bohn + If you require a license, see + http://www.opensource.org/licenses/bsd-license.php +*/ + +#ifndef _ESP8266AVRISP_H +#define _ESP8266AVRISP_H + +#include + +// uncomment if you use an n-mos to level-shift the reset line +// #define AVRISP_ACTIVE_HIGH_RESET + +// SPI clock frequency in Hz +#define AVRISP_SPI_FREQ 300e3 + +// programmer states +typedef enum { + AVRISP_STATE_IDLE = 0, // no active TCP session + AVRISP_STATE_PENDING, // TCP connected, pending SPI activation + AVRISP_STATE_ACTIVE // programmer is active and owns the SPI bus +} AVRISPState_t; + +// stk500 parameters +typedef struct { + uint8_t devicecode; + uint8_t revision; + uint8_t progtype; + uint8_t parmode; + uint8_t polling; + uint8_t selftimed; + uint8_t lockbytes; + uint8_t fusebytes; + int flashpoll; + int eeprompoll; + int pagesize; + int eepromsize; + int flashsize; +} AVRISP_parameter_t; + + +class ESP8266AVRISP { +public: + ESP8266AVRISP(uint16_t port, uint8_t reset_pin, uint32_t spi_freq=AVRISP_SPI_FREQ, bool reset_state=false); + + void begin(); + + // set the SPI clock frequency + void setSpiFrequency(uint32_t); + + // control the state of the RESET pin of the target + // see AVRISP_ACTIVE_HIGH_RESET + void setReset(bool); + + // check for pending clients if IDLE, check for disconnect otherwise + // returns the updated state + AVRISPState_t update(); + + // transition to ACTIVE if PENDING + // serve STK500 commands from buffer if ACTIVE + // returns the updated state + AVRISPState_t serve(); + +protected: + + inline void _reject_incoming(void); // reject any incoming tcp connections + + int avrisp(void); // handle incoming STK500 commands + + uint8_t getch(void); // retrieve a character from the remote end + uint8_t spi_transaction(uint8_t, uint8_t, uint8_t, uint8_t); + void empty_reply(void); + void breply(uint8_t); + + void get_parameter(uint8_t); + void set_parameters(void); + int addr_page(int); + void flash(uint8_t, int, uint8_t); + void write_flash(int); + uint8_t write_flash_pages(int length); + uint8_t write_eeprom(int length); + uint8_t write_eeprom_chunk(int start, int length); + void commit(int addr); + void program_page(); + uint8_t flash_read(uint8_t hilo, int addr); + void flash_read_page(int length); + void eeprom_read_page(int length); + void read_page(); + void read_signature(); + + void universal(void); + + void fill(int); // fill the buffer with n bytes + void start_pmode(void); // enter program mode + void end_pmode(void); // exit program mode + + + + uint32_t _spi_freq; + WiFiServer _server; + WiFiClient _client; + AVRISPState_t _state; + uint8_t _reset_pin; + bool _reset_state; + + // programmer settings, set by remote end + AVRISP_parameter_t param; + // page buffer + uint8_t buff[256]; + + int error = 0; + bool pmode = 0; + + // address for reading and writing, set by 'U' command + int here; +}; + + +#endif // _ESP8266AVRISP_H diff --git a/libraries/ESP8266AVRISP/src/command.h b/libraries/ESP8266AVRISP/src/command.h new file mode 100644 index 000000000..2adc22bd3 --- /dev/null +++ b/libraries/ESP8266AVRISP/src/command.h @@ -0,0 +1,108 @@ +//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************ +//* +//* Title: AVR061 - STK500 Communication Protocol +//* Filename: command.h +//* Version: 1.0 +//* Last updated: 09.09.2002 +//* +//* Support E-mail: avr@atmel.com +//* +//************************************************************************** + +// *****************[ STK Message constants ]*************************** + +#define STK_SIGN_ON_MESSAGE "AVR STK" // Sign on string for Cmnd_STK_GET_SIGN_ON + +// *****************[ STK Response constants ]*************************** + +#define Resp_STK_OK 0x10 // ' ' +#define Resp_STK_FAILED 0x11 // ' ' +#define Resp_STK_UNKNOWN 0x12 // ' ' +#define Resp_STK_NODEVICE 0x13 // ' ' +#define Resp_STK_INSYNC 0x14 // ' ' +#define Resp_STK_NOSYNC 0x15 // ' ' + +#define Resp_ADC_CHANNEL_ERROR 0x16 // ' ' +#define Resp_ADC_MEASURE_OK 0x17 // ' ' +#define Resp_PWM_CHANNEL_ERROR 0x18 // ' ' +#define Resp_PWM_ADJUST_OK 0x19 // ' ' + +// *****************[ STK Special constants ]*************************** + +#define Sync_CRC_EOP 0x20 // 'SPACE' + +// *****************[ STK Command constants ]*************************** + +#define Cmnd_STK_GET_SYNC 0x30 // ' ' +#define Cmnd_STK_GET_SIGN_ON 0x31 // ' ' +#define Cmnd_STK_RESET 0x32 // ' ' +#define Cmnd_STK_SINGLE_CLOCK 0x33 // ' ' +#define Cmnd_STK_STORE_PARAMETERS 0x34 // ' ' + +#define Cmnd_STK_SET_PARAMETER 0x40 // ' ' +#define Cmnd_STK_GET_PARAMETER 0x41 // ' ' +#define Cmnd_STK_SET_DEVICE 0x42 // ' ' +#define Cmnd_STK_GET_DEVICE 0x43 // ' ' +#define Cmnd_STK_GET_STATUS 0x44 // ' ' +#define Cmnd_STK_SET_DEVICE_EXT 0x45 // ' ' + +#define Cmnd_STK_ENTER_PROGMODE 0x50 // ' ' +#define Cmnd_STK_LEAVE_PROGMODE 0x51 // ' ' +#define Cmnd_STK_CHIP_ERASE 0x52 // ' ' +#define Cmnd_STK_CHECK_AUTOINC 0x53 // ' ' +#define Cmnd_STK_CHECK_DEVICE 0x54 // ' ' +#define Cmnd_STK_LOAD_ADDRESS 0x55 // ' ' +#define Cmnd_STK_UNIVERSAL 0x56 // ' ' + +#define Cmnd_STK_PROG_FLASH 0x60 // ' ' +#define Cmnd_STK_PROG_DATA 0x61 // ' ' +#define Cmnd_STK_PROG_FUSE 0x62 // ' ' +#define Cmnd_STK_PROG_LOCK 0x63 // ' ' +#define Cmnd_STK_PROG_PAGE 0x64 // ' ' +#define Cmnd_STK_PROG_FUSE_EXT 0x65 // ' ' + +#define Cmnd_STK_READ_FLASH 0x70 // ' ' +#define Cmnd_STK_READ_DATA 0x71 // ' ' +#define Cmnd_STK_READ_FUSE 0x72 // ' ' +#define Cmnd_STK_READ_LOCK 0x73 // ' ' +#define Cmnd_STK_READ_PAGE 0x74 // ' ' +#define Cmnd_STK_READ_SIGN 0x75 // ' ' +#define Cmnd_STK_READ_OSCCAL 0x76 // ' ' +#define Cmnd_STK_READ_FUSE_EXT 0x77 // ' ' +#define Cmnd_STK_READ_OSCCAL_EXT 0x78 // ' ' + +// *****************[ STK Parameter constants ]*************************** + +#define Parm_STK_HW_VER 0x80 // ' ' - R +#define Parm_STK_SW_MAJOR 0x81 // ' ' - R +#define Parm_STK_SW_MINOR 0x82 // ' ' - R +#define Parm_STK_LEDS 0x83 // ' ' - R/W +#define Parm_STK_VTARGET 0x84 // ' ' - R/W +#define Parm_STK_VADJUST 0x85 // ' ' - R/W +#define Parm_STK_OSC_PSCALE 0x86 // ' ' - R/W +#define Parm_STK_OSC_CMATCH 0x87 // ' ' - R/W +#define Parm_STK_RESET_DURATION 0x88 // ' ' - R/W +#define Parm_STK_SCK_DURATION 0x89 // ' ' - R/W + +#define Parm_STK_BUFSIZEL 0x90 // ' ' - R/W, Range {0..255} +#define Parm_STK_BUFSIZEH 0x91 // ' ' - R/W, Range {0..255} +#define Parm_STK_DEVICE 0x92 // ' ' - R/W, Range {0..255} +#define Parm_STK_PROGMODE 0x93 // ' ' - 'P' or 'S' +#define Parm_STK_PARAMODE 0x94 // ' ' - TRUE or FALSE +#define Parm_STK_POLLING 0x95 // ' ' - TRUE or FALSE +#define Parm_STK_SELFTIMED 0x96 // ' ' - TRUE or FALSE + + +// *****************[ STK status bit definitions ]*************************** + +#define Stat_STK_INSYNC 0x01 // INSYNC status bit, '1' - INSYNC +#define Stat_STK_PROGMODE 0x02 // Programming mode, '1' - PROGMODE +#define Stat_STK_STANDALONE 0x04 // Standalone mode, '1' - SM mode +#define Stat_STK_RESET 0x08 // RESET button, '1' - Pushed +#define Stat_STK_PROGRAM 0x10 // Program button, ' 1' - Pushed +#define Stat_STK_LEDG 0x20 // Green LED status, '1' - Lit +#define Stat_STK_LEDR 0x40 // Red LED status, '1' - Lit +#define Stat_STK_LEDBLINK 0x80 // LED blink ON/OFF, '1' - Blink + + +// *****************************[ End Of COMMAND.H ]**************************