A fork of mAVRISP by Aaron Berk. This version does not use a local file system to hold the AVR program. Instead it uses a serial connection to a PC and a python script to send the AVR program to the mbed.

Dependencies:   mbed

Fork of mAVRISP by Aaron Berk

Files at this revision

API Documentation at this revision

Comitter:
jeroenmbed
Date:
Sat Jan 31 22:44:09 2015 +0000
Parent:
3:df6782d01720
Commit message:
Cleaned up.

Changed in this revision

AVR910.cpp Show diff for this revision Revisions of this file
AVR910.h Show diff for this revision Revisions of this file
AVR910_Serial.cpp Show annotated file Show diff for this revision Revisions of this file
AVR910_Serial.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r df6782d01720 -r ceee1eb7062e AVR910.cpp
--- a/AVR910.cpp	Sat Jan 31 21:54:05 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-/**
- * @author Aaron Berk
- *
- * @section LICENSE
- *
- * Copyright (c) 2010 Aaron Berk
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @section DESCRIPTION
- *
- * Program AVR chips with the AVR910 ISP (in-system programming) protocol,
- * using an mbed.
- *
- * AVR910 Application Note:
- *
- * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
- */
-
-/**
- * Includes
- */
-#include "AVR910.h"
-
-Serial debug(USBTX, USBRX);
-
-AVR910::AVR910(PinName mosi,
-               PinName miso,
-               PinName sclk,
-               PinName nReset) : spi_(mosi, miso, sclk), nReset_(nReset)
-{
-
-    //Slow frequency as default to ensure no errors from
-    //trying to run it too fast. Increase as appropriate.
-    spi_.frequency(5000);
-    spi_.format(8, 0);
-
-    int response = 0;
-
-    //Enter serial programming mode by pulling reset line low.
-    nReset_ = 0;
-
-    //Wait 20ms before issuing first command.
-    wait_ms(20);
-
-    //Issue a programming enable command.
-    response = enableProgramming();
-    //printf("R=%d\n\r",response);
-
-    //Simple debugging to see if we get trapped
-    //in an infinite loop.
-
-    //TODO: introduce a timeout.
-    while (response < 0) {
-
-        //Give nReset a positive pulse.
-        nReset_ = 1;
-        wait_ms(20);
-        nReset_ = 0;
-        wait_ms(20);
-
-        //Issue another programming enable.
-        response = enableProgramming();
-        // printf("R=%d\n\r",response);
-
-    }
-
-
-}
-
-int AVR910::program(FILE* binary, int pageSize, int numPages)
-{
-
-    //Clear memory contents.
-    chipErase();
-
-    char pageOffset = 0;
-    int  pageNumber = 0;
-    int  address    = 0;
-    int  c          = 0;
-    int  highLow    = 0;
-
-    //We're dealing with paged memory.
-    if (numPages > 1) {
-
-        while ((c = getc(binary)) != EOF) {
-
-            //Page is fully loaded, time to write it to flash.
-            if (pageOffset == (pageSize)) {
-                writeFlashMemoryPage(pageNumber);
-
-                pageNumber++;
-                if (pageNumber > numPages) {
-                    break;
-                }
-                pageOffset = 0;
-            }
-
-            //Write low byte.
-            if (highLow == 0) {
-                loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
-                highLow = 1;
-            }
-            //Write high byte.
-            else {
-                loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
-                highLow = 0;
-                pageOffset++;
-            }
-
-        }
-
-    }
-    //We're dealing with non-paged memory.
-    else {
-
-        while ((c = getc(binary)) != EOF) {
-
-            //Write low byte.
-            if (highLow == 0) {
-                writeFlashMemoryByte(WRITE_LOW_FLASH_BYTE, address, c);
-                highLow = 1;
-            }
-            //Write high byte.
-            else {
-                writeFlashMemoryByte(WRITE_HIGH_FLASH_BYTE, address, c);
-                highLow = 0;
-                address++;
-
-                //Page size is our memory size in the non-paged memory case.
-                //Therefore if we've gone beyond our size break because we
-                //don't have any more room.
-                if (address > pageSize) {
-                    break;
-                }
-
-            }
-
-        }
-
-    }
-
-    //We might have partially filled up a page.
-    writeFlashMemoryPage(pageNumber);
-
-    int success = -1;
-    success = checkMemory(pageNumber, binary);
-
-    //Leave serial programming mode by pulling reset line high.
-    nReset_ = 1;
-
-    return success;
-
-}
-
-int AVR910::programData(char* myData, int fileSize, int pageSize, int numPages)
-{
-
-    //Clear memory contents.
-    chipErase();
-
-    char pageOffset = 0;
-    int  pageNumber = 0;
-    int  address    = 0;
-    int  c          = 0;
-    int  highLow    = 0;
-
-    //We're dealing with paged memory.
-//   if (numPages > 1) {
-
-    //while ((c = getc(binary)) != EOF) {
-    for (int i=0; i<fileSize; i++) {
-        c = myData[i];
-        printf("p %d: 0x%02x\n",i, myData[i]);
-        //Page is fully loaded, time to write it to flash.
-        if (pageOffset == (pageSize)) {
-            writeFlashMemoryPage(pageNumber);
-
-            pageNumber++;
-            if (pageNumber > numPages) {
-                break;
-            }
-            pageOffset = 0;
-        }
-
-        //Write low byte.
-        if (highLow == 0) {
-            loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
-            highLow = 1;
-        }
-        //Write high byte.
-        else {
-            loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
-            highLow = 0;
-            pageOffset++;
-        }
-
-    }
-
-//   }
-    //We're dealing with non-paged memory.
-//   else {
-//
-//        while ((c = getc(binary)) != EOF) {
-//
-//            //Write low byte.
-//            if (highLow == 0) {
-//                writeFlashMemoryByte(WRITE_LOW_FLASH_BYTE, address, c);
-//                highLow = 1;
-//            }
-//            //Write high byte.
-//            else {
-//                writeFlashMemoryByte(WRITE_HIGH_FLASH_BYTE, address, c);
-//                highLow = 0;
-//                address++;
-//
-//                //Page size is our memory size in the non-paged memory case.
-//                //Therefore if we've gone beyond our size break because we
-//                //don't have any more room.
-//                if (address > pageSize) {
-//                    break;
-//                }
-//
-//            }
-//
-//        }
-
-//   }
-
-    //We might have partially filled up a page.
-    writeFlashMemoryPage(pageNumber);
-
-    int success = -1;
-    //success = checkMemory(pageNumber, binary);
-    printf("Going to check memory\n");
-    success = checkMemoryData(pageNumber, myData, fileSize);
-
-    //Leave serial programming mode by pulling reset line high.
-    nReset_ = 1;
-
-    return success;
-
-}
-void AVR910::setFrequency(int frequency)
-{
-
-    spi_.frequency(frequency);
-
-}
-
-int AVR910::enableProgramming(void)
-{
-
-    int response = 0;
-    int error    = 0;
-
-
-    //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00
-    //Byte two echo'd back in byte three.
-    response = spi_.write(0xAC);
-    //printf("enableProgramming resp (should be ??) = %x\n\r",response);
-
-    response = spi_.write(0x53);
-    //printf("enableProgramming resp (should be 0xAC) = %x\n\r",response);
-
-    response = spi_.write(0x00);
-    //printf("enableProgramming resp (should be 0x53) = %x\n\r",response);
-
-    if (response == 0x53) {
-        error =  0;
-    } else {
-        error = -1;
-    }
-
-    response = spi_.write(0x00);
-    //printf("enableProgramming resp (should be 0x00) = %x\n\r",response);
-
-    return error;
-
-}
-
-void AVR910::poll(void)
-{
-
-    int response = 0;
-
-    do {
-        spi_.write(0xF0);
-        spi_.write(0x00);
-        spi_.write(0x00);
-        response = spi_.write(0x00);
-    } while ((response & 0x01) != 0);
-
-}
-
-int AVR910::readVendorCode(void)
-{
-
-    int response = 0;
-
-    //Issue read signature byte command.
-    //Address 0x00 is vendor code.
-    spi_.write(0x30);
-    spi_.write(0x00);
-    spi_.write(0x00);
-    //printf("r1=%d\n\r",spi_.write(0x00));
-    //printf("r2=%d\n\r",spi_.write(0x00));
-    response = spi_.write(0x00);
-    //printf("r3=%d\n\r",response);
-
-    return response;
-
-}
-
-int AVR910::readPartFamilyAndFlashSize(void)
-{
-
-    int response = 0;
-
-    //Issue read signature byte command.
-    //Address 0x01 is part family and flash size code.
-    spi_.write(0x30);
-    spi_.write(0x00);
-    spi_.write(0x01);
-    response = spi_.write(0x00);
-
-    return response;
-
-}
-
-int AVR910::readPartNumber(void)
-{
-
-    int response = 0;
-
-    //Issue read signature byte command.
-    //Address 0x02 is part number code.
-    spi_.write(0x30);
-    spi_.write(0x00);
-    spi_.write(0x02);
-    response = spi_.write(0x00);
-
-    return response;
-
-}
-
-void AVR910::chipErase(void)
-{
-
-    //Issue chip erase command.
-    spi_.write(0xAC);
-    spi_.write(0x80);
-    spi_.write(0x00);
-    spi_.write(0x00);
-
-    poll();
-
-    //Temporarily release reset line.
-    nReset_ = 1;
-    nReset_ = 0;
-
-}
-
-void AVR910::loadMemoryPage(int highLow, char address, char data)
-{
-
-    spi_.write(highLow);
-    spi_.write(0x00);
-    spi_.write(address & 0x3F);
-    spi_.write(data);
-
-    poll();
-
-}
-
-void AVR910::writeFlashMemoryByte(int highLow, int address, char data)
-{
-
-    spi_.write(highLow);
-    spi_.write(address & 0xFF00 >> 8);
-    spi_.write(address & 0x00FF);
-    spi_.write(data);
-
-}
-
-void AVR910::writeFlashMemoryPage(char pageNumber)
-{
-
-    spi_.write(0x4C);
-    spi_.write((pageNumber >> 2) & 0x3F);
-    spi_.write((pageNumber & 0x03) << 6);
-    spi_.write(0x00);
-
-    poll();
-
-}
-
-char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset)
-{
-
-    int response = 0;
-
-    spi_.write(highLow);
-    spi_.write((pageNumber >> 2) & 0x3F);
-    spi_.write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F));
-    response = spi_.write(0x00);
-
-    poll();
-
-    return response;
-
-}
-
-int AVR910::checkMemory(int numPages, FILE* binary)
-{
-
-    int success  = 0;
-    int response = 0;
-    char c       = 0;
-
-    //Go back to the beginning of the binary file.
-    fseek(binary, 0, SEEK_SET);
-
-    for (int i = 0; i < numPages; i++) {
-        for (int j = 0; j < PAGE_SIZE; j++) {
-            c = getc(binary);
-            //Read program memory low byte.
-            response = readProgramMemory(READ_LOW_BYTE, i, j);
-            //debug.printf("Low byte: 0x%02x\n", response);
-            if ( c != response ) {
-                //  debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response);
-                //  debug.printf("Correct byte is 0x%02x\n", c);
-                success = -1;
-            }
-
-            c = getc(binary);
-            //Read program memory high byte.
-            response = readProgramMemory(READ_HIGH_BYTE, i, j);
-            //debug.printf("High byte: 0x%02x\n", response);
-            if ( c != response ) {
-                // debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response);
-                // debug.printf("Correct byte is 0x%02x\n", c);
-                success = -1;
-            }
-        }
-    }
-
-    return success;
-
-}
-
-
-int AVR910::checkMemoryData(int numPages, char* myData, int fileSize)
-{
-
-    int success  = 0;
-    int response = 0;
-    char c       = 0;
-
-    //Go back to the beginning of the binary file.
-    //fseek(binary, 0, SEEK_SET);
-    int dpoint=0;
-    printf("about to start checking (numPages=%d pagesize=%d)\n",numPages, PAGE_SIZE);
-    for (int i = 0; i <= numPages; i++) {
-        for (int j = 0; j < PAGE_SIZE; j++) {
-
-            //c = getc(binary);
-            c = myData[dpoint];
-            //Read program memory low byte.
-            response = readProgramMemory(READ_LOW_BYTE, i, j);
-            //debug.printf("Low byte: 0x%02x\n", response);
-            printf("dpoint=%d Page %i low byte %i: 0x%02x (should be 0x%02x)\n", dpoint-1, i, j, response,c);
-            if ( c != response ) {
-                // debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response);
-                // debug.printf("Correct byte is 0x%02x\n", c);
-                success = -1;
-            }
-
-            //c = getc(binary);
-            dpoint++;
-            if (dpoint==fileSize) break;
-            c = myData[dpoint];
-            //Read program memory high byte.
-            response = readProgramMemory(READ_HIGH_BYTE, i, j);
-            printf("dpoint=%d Page %i high byte %i: 0x%02x (should be 0x%02x)\n", dpoint-1, i, j, response,c);
-
-            //debug.printf("High byte: 0x%02x\n", response);
-            if ( c != response ) {
-                // debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response);
-                //debug.printf("Correct byte is 0x%02x\n", c);
-                success = -1;
-            }
-            dpoint++;
-            if (dpoint==fileSize) break;
-        }
-    }
-
-    return success;
-
-}
diff -r df6782d01720 -r ceee1eb7062e AVR910.h
--- a/AVR910.h	Sat Jan 31 21:54:05 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/**
- * @author Aaron Berk
- *
- * @section LICENSE
- *
- * Copyright (c) 2010 Aaron Berk
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @section DESCRIPTION
- *
- * Program AVR chips with the AVR910 ISP (in-system programming) protocol,
- * using an mbed.
- *
- * AVR910 Application Note:
- *
- * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
- */
-
-#ifndef MBED_AVR910_H
-#define MBED_AVR910_H
-
-/**
- * Includes
- */
-#include "mbed.h"
-
-/**
- * Defines
- */
-
-#define PATH_TO_BINARY "local/T.bin"
-
-//Commands
-#define ATMEL_VENDOR_CODE     0x1E
-#define DEVICE_LOCKED         0x00
-#define WRITE_HIGH_BYTE       0x48
-#define WRITE_LOW_BYTE        0x40
-#define READ_HIGH_BYTE        0x28
-#define READ_LOW_BYTE         0x20
-#define WRITE_HIGH_FLASH_BYTE 0x68
-#define WRITE_LOW_FLASH_BYTE  0x60
-
-#define PAGE_SIZE         ATMEGA328P_PAGESIZE
-#define NUM_PAGES         ATMEGA328P_NUM_PAGES
-
-//ATMega328P
-#define ATMEGA328P_PAGESIZE  64 //Size in words.
-#define ATMEGA328P_NUM_PAGES 256
-
-/**
- * AVR910 ISP
- */
-class AVR910 {
-
-public:
-
-    /**
-     * Constructor.
-     *
-     * @param mosi mbed pin for MOSI SPI line.
-     * @param miso mbed pin for MISO SPI line.
-     * @param sclk mbed pin for SCLK SPI line.
-     * @param nReset mbed pin for not reset line on the ISP interface.
-     *
-     * Sends an enable programming command, allowing device registers to be
-     * read and commands sent.
-     */
-    AVR910(PinName mosi, PinName miso, PinName sclk, PinName nReset);
-
-    /**
-     * Program the AVR microcontroller connected to the mbed.
-     *
-     * Sends a chip erase command followed by writing the binary to the AVR
-     * page buffer and writing the page buffer to flash memory whenever it is
-     * full.
-     *
-     * @param binary File pointer to the binary file to be loaded onto the
-     *               AVR microcontroller.
-     * @param pageSize The size of one page on the device in words. If the
-     *                 device does not use paged memory, set this as the size
-     *                 of memory of the device in words.
-     * @param numPages The number of pages on the device. If the device does
-     *                 not use paged memory, set this to 1 (default).
-     *
-     * @return  0 => AVR microcontroller programmed successfully.
-     *         -1 => Problem during programming.
-     */
-    int program(FILE* binary, int pageSize, int numPages = 1);
-    int programData(char* myData, int fileSize, int pageSize, int numPages = 1);
-
-    /**
-     * Set the frequency of the SPI communication.
-     *
-     * (Wrapper for SPI::frequency)
-     *
-     * @param frequency Frequency of the SPI communication in hertz.
-     */
-    void setFrequency(int frequency);
-
-    /**
-     * Read the vendor code of the device.
-     *
-     * @return The vendor code - should be 0x1E for Atmel.
-     *         0x00 -> Device is locked.
-     */
-    int readVendorCode(void);
-
-    /**
-     * Read the part family and flash size of the device.
-     *
-     * @return Code indicating the family of AVR microcontrollers the device comes
-     *         from and how much flash memory it contains.
-     *         0xFF -> Device code erased or target missing.
-     *         0x01 -> Device is locked.
-     */
-    int readPartFamilyAndFlashSize(void);
-
-    /**
-     * Read the part number.
-     *
-     * @return Code identifying the part number.
-     *         0xFF -> Device code erased or target missing.
-     *         0x02 -> Device is locked.
-     */
-    int readPartNumber(void);
-
-private:
-
-    /**
-     * Issue an enable programming command to the AVR microcontroller.
-     *
-     * @param  0 to indicate programming was enabled successfully.
-     *        -1 to indicate programming was not enabled.
-     */
-    int enableProgramming(void);
-
-    /**
-     * Poll the device until it has finished its current operation.
-     */
-    void poll(void);
-
-    /**
-     * Issue a chip erase command to the AVR microcontroller.
-     */
-    void chipErase(void);
-
-    /**
-     * Load a byte into the memory page buffer.
-     *
-     * @param highLow Indicate whether the byte being loaded is a high or low
-     *                byte.
-     * @param data The data byte to load.
-     */
-    void loadMemoryPage(int highLow, char address, char data);
-
-    /**
-     * Write a byte into the flash memory.
-     *
-     * @param highLow Indicate whether the byte being loaded is a high or low
-     *                byte.
-     * @param address The address to load the byte at.
-     * @param data The data byte to load.
-     */
-    void writeFlashMemoryByte(int highLow, int address, char data);
-
-    /**
-     * Write the memory page buffer to flash memory.
-     *
-     * @param pageNumber The page number to write to in flash memory.
-     */
-    void writeFlashMemoryPage(char pageNumber);
-
-    /**
-     * Read a byte from program memory.
-     *
-     * @param highLow Indicate whether the byte being read is a low or high byte.
-     * @param pageNumber The page number to read from.
-     * @param pageOffset Address of byte in the page.
-     *
-     * @return The byte at the specified memory location.
-     */
-    char readProgramMemory(int highLow, char pageNumber, char pageOffset);
-
-    /**
-     * Check the binary has been written correctly.
-     *
-     * @param numPages The number of pages written to the AVR microcontroller.
-     * @param binary File pointer to the binary used.
-     *
-     * @return  0 -> No inconsistencies between binary file and AVR flash memory.
-     *         -1 -> Binary file was not written correctly.
-     */
-    int checkMemory(int numPages, FILE* binary);
-    int checkMemoryData(int numPages, char* myData, int fileSize);
-
-    SPI        spi_;
-    DigitalOut nReset_;
-
-};
-
-#endif /* AVR910_H */
diff -r df6782d01720 -r ceee1eb7062e AVR910_Serial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AVR910_Serial.cpp	Sat Jan 31 22:44:09 2015 +0000
@@ -0,0 +1,336 @@
+/**
+ * @author Aaron Berk, Jeroen Voogd
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2010 Aaron Berk
+ * Copyright (c) 2015 Jeroen Voogd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * Program AVR chips with the AVR910 ISP (in-system programming) protocol,
+ * using an mbed. The version of Aaron Berk used a local file system, this version
+ * useses a python script to feed the data via a serial connection.
+ *
+ * AVR910 Application Note:
+ *
+ * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
+ */
+
+/**
+ * Includes
+ */
+#include "AVR910_Serial.h"
+
+Serial debug(USBTX, USBRX);
+
+AVR910::AVR910(PinName mosi,
+               PinName miso,
+               PinName sclk,
+               PinName nReset) : spi_(mosi, miso, sclk), nReset_(nReset)
+{
+
+    //Slow frequency as default to ensure no errors from
+    //trying to run it too fast. Increase as appropriate.
+    spi_.frequency(32000);
+    spi_.format(8, 0);
+
+    int response = 0;
+
+    //Enter serial programming mode by pulling reset line low.
+    nReset_ = 0;
+
+    //Wait 20ms before issuing first command.
+    wait_ms(20);
+
+    //Issue a programming enable command.
+    response = enableProgramming();
+
+    //TODO: introduce a timeout.
+    while (response < 0) {
+
+        //Give nReset a positive pulse.
+        nReset_ = 1;
+        wait_ms(20);
+        nReset_ = 0;
+        wait_ms(20);
+
+        //Issue another programming enable.
+        response = enableProgramming();
+    }
+}
+
+
+int AVR910::programData(char* myData, int dataSize, int pageSize, int numPages)
+{
+
+    //Clear memory contents.
+    chipErase();
+
+    char pageOffset = 0;
+    int  pageNumber = 0;
+    int  c          = 0;
+    int  highLow    = 0;
+
+    //In this version we're always dealing with paged memory.
+
+    for (int i=0; i<dataSize; i++) {
+        c = myData[i];
+        //Page is fully loaded, time to write it to flash.
+        if (pageOffset == (pageSize)) {
+            writeFlashMemoryPage(pageNumber);
+
+            pageNumber++;
+            if (pageNumber > numPages) {
+                break;
+            }
+            pageOffset = 0;
+        }
+
+        //Write low byte.
+        if (highLow == 0) {
+            loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
+            highLow = 1;
+        }
+        //Write high byte.
+        else {
+            loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
+            highLow = 0;
+            pageOffset++;
+        }
+
+    }
+
+    //We might have partially filled up a page.
+    writeFlashMemoryPage(pageNumber);
+
+    int success = -1;
+    success = checkMemoryData(pageNumber, myData, dataSize);
+
+    //Leave serial programming mode by pulling reset line high.
+    nReset_ = 1;
+
+    return success;
+
+}
+void AVR910::setFrequency(int frequency)
+{
+
+    spi_.frequency(frequency);
+
+}
+
+int AVR910::enableProgramming(void)
+{
+
+    int response = 0;
+    int error    = 0;
+
+    //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00
+    //Byte two echo'd back in byte three.
+    spi_.write(0xAC);
+
+    spi_.write(0x53);
+
+    response = spi_.write(0x00);
+
+    if (response == 0x53) {
+        error =  0;
+    } else {
+        error = -1;
+    }
+
+    response = spi_.write(0x00);
+    
+    return error;
+
+}
+
+void AVR910::poll(void)
+{
+
+    int response = 0;
+
+    do {
+        spi_.write(0xF0);
+        spi_.write(0x00);
+        spi_.write(0x00);
+        response = spi_.write(0x00);
+    } while ((response & 0x01) != 0);
+
+}
+
+int AVR910::readVendorCode(void)
+{
+
+    int response = 0;
+
+    //Issue read signature byte command.
+    //Address 0x00 is vendor code.
+    spi_.write(0x30);
+    spi_.write(0x00);
+    spi_.write(0x00);
+    response = spi_.write(0x00);
+   
+    return response;
+
+}
+
+int AVR910::readPartFamilyAndFlashSize(void)
+{
+
+    int response = 0;
+
+    //Issue read signature byte command.
+    //Address 0x01 is part family and flash size code.
+    spi_.write(0x30);
+    spi_.write(0x00);
+    spi_.write(0x01);
+    response = spi_.write(0x00);
+
+    return response;
+
+}
+
+int AVR910::readPartNumber(void)
+{
+
+    int response = 0;
+
+    //Issue read signature byte command.
+    //Address 0x02 is part number code.
+    spi_.write(0x30);
+    spi_.write(0x00);
+    spi_.write(0x02);
+    response = spi_.write(0x00);
+
+    return response;
+
+}
+
+void AVR910::chipErase(void)
+{
+
+    //Issue chip erase command.
+    spi_.write(0xAC);
+    spi_.write(0x80);
+    spi_.write(0x00);
+    spi_.write(0x00);
+
+    poll();
+
+    //Temporarily release reset line.
+    nReset_ = 1;
+    nReset_ = 0;
+
+}
+
+void AVR910::loadMemoryPage(int highLow, char address, char data)
+{
+
+    spi_.write(highLow);
+    spi_.write(0x00);
+    spi_.write(address & 0x3F);
+    spi_.write(data);
+
+    poll();
+
+}
+
+void AVR910::writeFlashMemoryByte(int highLow, int address, char data)
+{
+
+    spi_.write(highLow);
+    spi_.write(address & 0xFF00 >> 8);
+    spi_.write(address & 0x00FF);
+    spi_.write(data);
+
+}
+
+void AVR910::writeFlashMemoryPage(char pageNumber)
+{
+
+    spi_.write(0x4C);
+    spi_.write((pageNumber >> 2) & 0x3F);
+    spi_.write((pageNumber & 0x03) << 6);
+    spi_.write(0x00);
+
+    poll();
+
+}
+
+char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset)
+{
+
+    int response = 0;
+
+    spi_.write(highLow);
+    spi_.write((pageNumber >> 2) & 0x3F);
+    spi_.write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F));
+    response = spi_.write(0x00);
+
+    poll();
+
+    return response;
+
+}
+
+
+int AVR910::checkMemoryData(int numPages, char* myData, int dataSize)
+{
+    
+    int success  = 0;
+    int response = 0;
+    char c       = 0;
+
+    // start at the beginning of the original data
+    int dpoint=0;
+    
+    for (int i = 0; i <= numPages; i++) {
+        for (int j = 0; j < PAGE_SIZE; j++) {
+
+            c = myData[dpoint];
+            //Read program memory low byte.
+            response = readProgramMemory(READ_LOW_BYTE, i, j);
+            if ( c != response ) {
+                success = -1;
+            }
+            
+            // next data item to check, break if all data has been checked
+            dpoint++;
+            if (dpoint==dataSize) break;
+            c = myData[dpoint];
+            
+            //Read program memory high byte.
+            response = readProgramMemory(READ_HIGH_BYTE, i, j);
+            if ( c != response ) {
+                success = -1;
+            }
+            
+            // next data item to check, break if all data has been checked
+            dpoint++;
+            if (dpoint==dataSize) break;
+        }
+    }
+
+    return success;
+
+}
diff -r df6782d01720 -r ceee1eb7062e AVR910_Serial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AVR910_Serial.h	Sat Jan 31 22:44:09 2015 +0000
@@ -0,0 +1,216 @@
+/**
+ * * @author Aaron Berk, Jeroen Voogd
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2010 Aaron Berk
+ * Copyright (c) 2015 Jeroen Voogd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * Program AVR chips with the AVR910 ISP (in-system programming) protocol,
+ * using an mbed. The version of Aaron Berk used a local file system, this version
+ * useses a python script to feed the data via a serial connection.
+ *
+ * AVR910 Application Note:
+ *
+ * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
+ */
+
+#ifndef MBED_AVR910_H
+#define MBED_AVR910_H
+
+/**
+ * Includes
+ */
+#include "mbed.h"
+
+/**
+ * Defines
+ */
+
+//Commands
+#define ATMEL_VENDOR_CODE     0x1E
+#define DEVICE_LOCKED         0x00
+#define WRITE_HIGH_BYTE       0x48
+#define WRITE_LOW_BYTE        0x40
+#define READ_HIGH_BYTE        0x28
+#define READ_LOW_BYTE         0x20
+#define WRITE_HIGH_FLASH_BYTE 0x68
+#define WRITE_LOW_FLASH_BYTE  0x60
+
+#define PAGE_SIZE         ATMEGA328P_PAGESIZE
+#define NUM_PAGES         ATMEGA328P_NUM_PAGES
+
+//ATMega328P
+#define ATMEGA328P_PAGESIZE  64 //Size in words.
+#define ATMEGA328P_NUM_PAGES 256
+
+/**
+ * AVR910 ISP
+ */
+class AVR910 {
+
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param mosi mbed pin for MOSI SPI line.
+     * @param miso mbed pin for MISO SPI line.
+     * @param sclk mbed pin for SCLK SPI line.
+     * @param nReset mbed pin for not reset line on the ISP interface.
+     *
+     * Sends an enable programming command, allowing device registers to be
+     * read and commands sent.
+     */
+    AVR910(PinName mosi, PinName miso, PinName sclk, PinName nReset);
+
+    /**
+     * Program the AVR microcontroller connected to the mbed.
+     *
+     * Sends a chip erase command followed by writing the binary to the AVR
+     * page buffer and writing the page buffer to flash memory whenever it is
+     * full.
+     * @param myData The char array with the bytes of the program to be flashed.
+     * @param dataSize The number of bytes to be flashed
+     * @param pageSize The size of one page on the device in words. If the
+     *                 device does not use paged memory, set this as the size
+     *                 of memory of the device in words.
+     * @param numPages The number of pages on the device. If the device does
+     *                 not use paged memory, set this to 1 (default).
+     *
+     * @return  0 => AVR microcontroller programmed successfully.
+     *         -1 => Problem during programming.
+     */
+    int programData(char* myData, int dataSize, int pageSize, int numPages = 1);
+
+    /**
+     * Set the frequency of the SPI communication.
+     *
+     * (Wrapper for SPI::frequency)
+     *
+     * @param frequency Frequency of the SPI communication in hertz.
+     */
+    void setFrequency(int frequency);
+
+    /**
+     * Read the vendor code of the device.
+     *
+     * @return The vendor code - should be 0x1E for Atmel.
+     *         0x00 -> Device is locked.
+     */
+    int readVendorCode(void);
+
+    /**
+     * Read the part family and flash size of the device.
+     *
+     * @return Code indicating the family of AVR microcontrollers the device comes
+     *         from and how much flash memory it contains.
+     *         0xFF -> Device code erased or target missing.
+     *         0x01 -> Device is locked.
+     */
+    int readPartFamilyAndFlashSize(void);
+
+    /**
+     * Read the part number.
+     *
+     * @return Code identifying the part number.
+     *         0xFF -> Device code erased or target missing.
+     *         0x02 -> Device is locked.
+     */
+    int readPartNumber(void);
+
+private:
+
+    /**
+     * Issue an enable programming command to the AVR microcontroller.
+     *
+     * @param  0 to indicate programming was enabled successfully.
+     *        -1 to indicate programming was not enabled.
+     */
+    int enableProgramming(void);
+
+    /**
+     * Poll the device until it has finished its current operation.
+     */
+    void poll(void);
+
+    /**
+     * Issue a chip erase command to the AVR microcontroller.
+     */
+    void chipErase(void);
+
+    /**
+     * Load a byte into the memory page buffer.
+     *
+     * @param highLow Indicate whether the byte being loaded is a high or low
+     *                byte.
+     * @param data The data byte to load.
+     */
+    void loadMemoryPage(int highLow, char address, char data);
+
+    /**
+     * Write a byte into the flash memory.
+     *
+     * @param highLow Indicate whether the byte being loaded is a high or low
+     *                byte.
+     * @param address The address to load the byte at.
+     * @param data The data byte to load.
+     */
+    void writeFlashMemoryByte(int highLow, int address, char data);
+
+    /**
+     * Write the memory page buffer to flash memory.
+     *
+     * @param pageNumber The page number to write to in flash memory.
+     */
+    void writeFlashMemoryPage(char pageNumber);
+
+    /**
+     * Read a byte from program memory.
+     *
+     * @param highLow Indicate whether the byte being read is a low or high byte.
+     * @param pageNumber The page number to read from.
+     * @param pageOffset Address of byte in the page.
+     *
+     * @return The byte at the specified memory location.
+     */
+    char readProgramMemory(int highLow, char pageNumber, char pageOffset);
+
+    /**
+     * Check the binary has been written correctly.
+     *
+     * @param numPages The number of pages written to the AVR microcontroller.
+     * @param myData The char array with the bytes of the program to be flashed.
+     * @param dataSize The number of bytes to be flashed
+     *
+     * @return  0 -> No inconsistencies between binary file and AVR flash memory.
+     *         -1 -> Binary file was not written correctly.
+     */
+    int checkMemoryData(int numPages, char* myData, int dataSize);
+
+    SPI        spi_;
+    DigitalOut nReset_;
+
+};
+
+#endif /* AVR910_H */
diff -r df6782d01720 -r ceee1eb7062e main.cpp
--- a/main.cpp	Sat Jan 31 21:54:05 2015 +0000
+++ b/main.cpp	Sat Jan 31 22:44:09 2015 +0000
@@ -1,29 +1,27 @@
 /**
  * Program an AVR with an mbed.
+ * The mbed is connected to an ATMEGA328 via ISP.
+ * The PC has a serial connection to the mbed.
+ * The AVR program on the PC is send via the serial connection to the mbed using a python script.
+ * The mbed then programs the ATMEGA328 via ISP.
  */
 
-#include "AVR910.h"
+#include "AVR910_Serial.h"
+#include "mbed.h"
 
-//LocalFileSystem local("local");
+// serial connection to a pc
 Serial pc(USBTX, USBRX);
-//AVR910 mAVRISP(PA_7, PA_6, PA_5, PB_6); //mosi, miso, sclk, nreset.
-//AVR910 mAVRISP(PB_5, PB_4, PB_3, PA_10); //mosi, miso, sclk, nreset.
+// ISP programmer
 AVR910 mAVRISP(PB_15, PB_14, PB_13, PB_2); //mosi, miso, sclk, nreset.
 
-DigitalOut working(LED1);
-
-
 int main()
 {
-    working = 1;
     int success  = -1;
     int response =  0;
 
-    pc.printf("Starting\n");
-
     //Read the vendor code [0x1E == Atmel].
     response = mAVRISP.readVendorCode();
-    printf("vendorcode=%d\n",response);
+
     if (response == ATMEL_VENDOR_CODE) {
         pc.printf("Microcontroller is an Atmel [0x%02x]\n", response);
     } else if (response == DEVICE_LOCKED) {
@@ -58,58 +56,44 @@
         pc.printf("Part number code is: 0x%02x\n", response);
     }
 
-    //Open binary file to write to AVR.
-    //FILE *fp = fopen(PATH_TO_BINARY, "rb");
+    // signal the python script it can start sending the file size
     printf("@");
-    
+
     int hs, ls;
     while (!pc.readable());
     hs = pc.getc();
-    printf("hs=%d\n",hs);
     while (!pc.readable());
     ls = pc.getc();
-    printf("ls=%d\n",ls);
-    int fileSize = (hs<<8) + ls;
-    printf ("file size = %d\n", fileSize);
+    int dataSize = (hs<<8) + ls;
 
+    // signal the python script it can start sending the file
     printf("#");
-    
+
     char *myFile;
-    myFile = new char [fileSize];
+    myFile = new char [dataSize];
     int readChar=0;
-    while (readChar < fileSize) {
+    while (readChar < dataSize) {
         if (pc.readable()) {
             myFile[readChar]=pc.getc();
             readChar++;
         }
     }
-    for (int i=0; i<fileSize; i++) {
-        printf("r %d: 0x%02x\n",i, myFile[i]);
-    }
-    wait_ms(1000);
-    success = mAVRISP.programData(myFile, fileSize, ATMEGA328P_PAGESIZE, ATMEGA328P_NUM_PAGES);
 
-//    if (fp == NULL) {
-//        pc.printf("Failed to open binary. Please check the file path\n");
-//        return -1;
-//    } else {
-//        //Program it!
-//        pc.printf("Binary file opened successfully\n");
-//        success = mAVRISP.program(fp,
-//                                  ATMEGA328P_PAGESIZE,
-//                                  ATMEGA328P_NUM_PAGES);
-//        fclose(fp);
-//    }
+    // program the atmega
+    success = mAVRISP.programData(myFile, dataSize, ATMEGA328P_PAGESIZE, ATMEGA328P_NUM_PAGES);
 
     if (success < 0) {
         printf("Programming failed.\n");
     } else {
         printf("Programming was successful!\n");
     }
+    
+    // signal the python script it can stop
+    printf("$");
 
 }
 
-/* Python file for on the pc:
+/* Python script to be run on the pc:
 import serial
 import sys
 import os
@@ -124,21 +108,18 @@
     if s.readable():
         c = s.read()
         if '@' in c:
-            print "Start sending file size\n"
             hs = (fileSize>>8) & 0xff
             s.write(chr(hs))
             ls = fileSize & 0xff
             s.write(chr(ls))
-        if '#' in c:
-            print "Start sending file\n"
+        elif '#' in c:
             with open(fileName, "rb") as f:
                 byte = f.read(1)
                 while byte != "":
-#                    while not s.writable():
-#                        pass
-#                    print "send: 0x",format(ord(byte),'02x')
                     s.write(byte)
                     byte = f.read(1)
+        elif '$' in c:
+            break
         else:
             sys.stdout.write(c)
 */
@@ -151,15 +132,21 @@
 int main(void)
 {
 // Set Port D pins as all outputs
-DDRD = 0xff;
+    DDRD = 0xff;
 
 // Set all Port D pins as HIGH
-while (1) {
-PORTD = 0xFF;
-_delay_ms(500.);
-PORTD = 0x00;
-_delay_ms(500.);
+    while (1) {
+        PORTD = 0xFF;
+        _delay_ms(500.);
+        PORTD = 0x00;
+        _delay_ms(500.);
+    }
+    return 1;
 }
-return 1;
-}
+
+The avr test file needs to be compiled, linked (make + make hex) to get a .hex file.
+This hex needs to be transformed into a .bin file via hex2bin.
+Make sure the mbed is up and running with the code in this file.
+Then uploaded the .bin via the python script: python scriptName programName.bin
+A reset of the mbed board may be needed.
 */
\ No newline at end of file