summaryrefslogtreecommitdiffstats
path: root/commandline
diff options
context:
space:
mode:
authorJenna Fox <a@creativepony.com>2012-10-02 14:33:44 +1000
committerJenna Fox <a@creativepony.com>2012-10-02 14:33:44 +1000
commit85669da5c3101b2e8c815e257a5e17615ada26f5 (patch)
tree4614b5d0044cd849058d28fc609bf666418da6e6 /commandline
parentf8b910e8f0da193c643c5857063be07ef67cbe79 (diff)
downloadmicronucleus-85669da5c3101b2e8c815e257a5e17615ada26f5.tar.gz
micronucleus-85669da5c3101b2e8c815e257a5e17615ada26f5.tar.bz2
micronucleus-85669da5c3101b2e8c815e257a5e17615ada26f5.zip
Added percentage progress to CLI upload tool and worked on consistent style throughout commandline c code (all variables underscore_cased, all functions lowerCamelCased).
Diffstat (limited to 'commandline')
-rw-r--r--commandline/examples/micronucleus.c497
-rw-r--r--commandline/library/micronucleus_lib.c242
-rw-r--r--commandline/library/micronucleus_lib.h75
3 files changed, 435 insertions, 379 deletions
diff --git a/commandline/examples/micronucleus.c b/commandline/examples/micronucleus.c
index c0530f2..5fb4c32 100644
--- a/commandline/examples/micronucleus.c
+++ b/commandline/examples/micronucleus.c
@@ -1,24 +1,24 @@
/*
- Created: September 2012
- by ihsan Kehribar <ihsan@kehribar.me>
-
- 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:
+ Created: September 2012
+ by ihsan Kehribar <ihsan@kehribar.me>
+
+ 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 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.
+ 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.
*/
#include <stdio.h>
@@ -30,11 +30,12 @@
#define FILE_TYPE_INTEL_HEX 1
#define FILE_TYPE_RAW 2
+#define CONNECT_WAIT 750 /* milliseconds to wait after detecting device on usb bus - probably excessive */
/******************************************************************************
* Global definitions
******************************************************************************/
-unsigned char dataBuffer[65536 + 256]; /* buffer for file data */
+unsigned char dataBuffer[65536 + 256]; /* buffer for file data */
/*****************************************************************************/
/******************************************************************************
@@ -44,246 +45,292 @@ static int parseRaw(char *hexfile, char* buffer, int *startAddr, int *endAddr);
static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAddr); /* taken from bootloadHID example from obdev */
static int parseUntilColon(FILE *fp); /* taken from bootloadHID example from obdev */
static int parseHex(FILE *fp, int numDigits); /* taken from bootloadHID example from obdev */
+static void printProgress(float progress);
+static void setProgressData(char* friendly, int step);
+static int progress_step = 0; // current step
+static int progress_total_steps = 0; // total steps for upload
+static char* progress_friendly_name; // name of progress section
+static int dump_progress = 0; // output computer friendly progress info
/*****************************************************************************/
/******************************************************************************
* Main function!
******************************************************************************/
-int main(int argc, char **argv)
-{
- int res;
- char *file = NULL;
- micronucleus *myDevice = NULL;
+int main(int argc, char **argv) {
+ int res;
+ char *file = NULL;
+ micronucleus *my_device = NULL;
- // parse arguments
- int run = 0;
- int file_type = FILE_TYPE_INTEL_HEX;
- int arg_pointer = 1;
- char* usage = "usage: micronucleus [--run] [--type intel-hex|raw] [<intel-hexfile>|-]";
-
- while (arg_pointer < argc) {
- if (strcmp(argv[arg_pointer], "--run") == 0) {
- run = 1;
- } else if (strcmp(argv[arg_pointer], "--type") == 0) {
- arg_pointer += 1;
- if (strcmp(argv[arg_pointer], "intel-hex") == 0) {
- file_type = FILE_TYPE_INTEL_HEX;
- } else if (strcmp(argv[arg_pointer], "raw") == 0) {
- file_type = FILE_TYPE_RAW;
- } else {
- printf("Unknown File Type specified with --type option");
- }
- } else if (strcmp(argv[arg_pointer], "--help") == 0 || strcmp(argv[arg_pointer], "-h") == 0) {
- puts(usage);
- return EXIT_SUCCESS;
- } else {
- file = argv[arg_pointer];
- }
- arg_pointer += 1;
+ // parse arguments
+ int run = 0;
+ int file_type = FILE_TYPE_INTEL_HEX;
+ int arg_pointer = 1;
+ char* usage = "usage: micronucleus [--run] [--dump-progress] [--type intel-hex|raw] [<intel-hexfile>|-]";
+ progress_step = 0;
+ progress_total_steps = 5; // steps: waiting, connecting, parsing, erasing, writing, (running)?
+ dump_progress = 0;
+
+ while (arg_pointer < argc) {
+ if (strcmp(argv[arg_pointer], "--run") == 0) {
+ run = 1;
+ progress_total_steps += 1;
+ } else if (strcmp(argv[arg_pointer], "--type") == 0) {
+ arg_pointer += 1;
+ if (strcmp(argv[arg_pointer], "intel-hex") == 0) {
+ file_type = FILE_TYPE_INTEL_HEX;
+ } else if (strcmp(argv[arg_pointer], "raw") == 0) {
+ file_type = FILE_TYPE_RAW;
+ } else {
+ printf("Unknown File Type specified with --type option");
+ }
+ } else if (strcmp(argv[arg_pointer], "--help") == 0 || strcmp(argv[arg_pointer], "-h") == 0) {
+ puts(usage);
+ return EXIT_SUCCESS;
+ } else if (strcmp(argv[arg_pointer], "--dump-progress") == 0) {
+ dump_progress = 1;
+ } else {
+ file = argv[arg_pointer];
}
- if (argc < 2) {
- puts(usage);
- return EXIT_FAILURE;
- }
-
-
- printf("> Please plug the device ... \n");
- printf("> Press CTRL+C to terminate the program.\n");
-
- while(myDevice == NULL)
- {
- myDevice = micronucleus_connect();
- delay(250);
- }
-
- printf("> Device is found!\n");
-
- delay(750);
- myDevice = micronucleus_connect();
-
- if(myDevice->page_size == 64)
- {
- printf("> Device looks like ATtiny85!\n");
- }
- else if(myDevice->page_size == 32)
- {
- printf("> Device looks like ATtiny45!\n");
- }
- else
- {
- printf("> Unsupported device!\n");
- return EXIT_FAILURE;
- }
-
- printf("> Available space for user application: %d bytes\n", myDevice->flash_size);
- printf("> Suggested sleep time between sending pages: %ums\n", myDevice->write_sleep);
- printf("> Whole page count: %d\n", myDevice->pages);
- printf("> Erase function sleep duration: %dms\n", myDevice->erase_sleep);
-
- memset(dataBuffer, 0xFF, sizeof(dataBuffer));
+ arg_pointer += 1;
+ }
+
+ if (argc < 2) {
+ puts(usage);
+ return EXIT_FAILURE;
+ }
+
+ setProgressData("waiting", 1);
+ printProgress(0.5);
+ printf("> Please plug the device ... \n");
+ printf("> Press CTRL+C to terminate the program.\n");
+
+ while (my_device == NULL) {
+ my_device = micronucleus_connect();
+ delay(250);
+ }
+
+ printf("> Device is found!\n");
+
+ // wait for CONNECT_WAIT milliseconds with progress output
+ float wait = 0.0f;
+ setProgressData("connecting", 2);
+ while (wait < CONNECT_WAIT) {
+ printProgress((wait / ((float) CONNECT_WAIT)) * 0.9f);
+ wait += 50.0f;
+ delay(50);
+ }
+
+ my_device = micronucleus_connect();
+ printProgress(1.0);
- int startAddress = 1, endAddress = 0;
- if (file_type = FILE_TYPE_INTEL_HEX) {
- if (parseIntelHex(file, dataBuffer, &startAddress, &endAddress)) {
- printf("> Error loading or parsing hex file.\n");
- return EXIT_FAILURE;
- }
- } else if (FILE_TYPE_RAW) {
- if (parseRaw(file, dataBuffer, &startAddress, &endAddress)) {
- printf("> Error loading raw file.\n");
- return EXIT_FAILURE;
- }
+ if (my_device->page_size == 64) {
+ printf("> Device looks like ATtiny85!\n");
+ }
+ else if (my_device->page_size == 32) {
+ printf("> Device looks like ATtiny45!\n");
+ } else {
+ printf("> Unsupported device!\n");
+ return EXIT_FAILURE;
+ }
+
+ printf("> Available space for user application: %d bytes\n", my_device->flash_size);
+ printf("> Suggested sleep time between sending pages: %ums\n", my_device->write_sleep);
+ printf("> Whole page count: %d\n", my_device->pages);
+ printf("> Erase function sleep duration: %dms\n", my_device->erase_sleep);
+
+ setProgressData("parsing", 3);
+ printProgress(0.0);
+ memset(dataBuffer, 0xFF, sizeof(dataBuffer));
+
+ int startAddress = 1, endAddress = 0;
+ if (file_type = FILE_TYPE_INTEL_HEX) {
+ if (parseIntelHex(file, dataBuffer, &startAddress, &endAddress)) {
+ printf("> Error loading or parsing hex file.\n");
+ return EXIT_FAILURE;
}
-
- if(startAddress >= endAddress)
- {
- printf("> No data in input file, exiting.\n");
- return EXIT_FAILURE;
- }
-
- if(endAddress > myDevice->flash_size)
- {
- printf("> Program file is %d bytes too big for the bootloader!\n", endAddress - myDevice->flash_size);
- return EXIT_FAILURE;
- }
-
- /* Prints the decoded intel hex file */
- /*printf("> Decoded hex file starts ... \n");
- for(i=startAddress;i<endAddress;i+=16)
- {
- printf("%5d:\t",i);
- for(k=0;k<16;k++)
- printf("%2X ",dataBuffer[i+k]);
- printf("\n");
- }
- printf("> Decoded hex file ends ... \n");*/
-
- printf("> Erasing the memory ...\n");
- res = micronucleus_eraseFlash(myDevice);
- if(res!=0)
- {
- printf(">> Abort mission! An error has occured ...\n");
- printf(">> Please unplug the device and restart the program. \n");
- return EXIT_FAILURE;
- }
-
- printf("> Starting to upload ...\n");
- res = micronucleus_writeFlash(myDevice,endAddress,dataBuffer);
- if(res!=0)
- {
- printf(">> Abort mission! An error has occured ...\n");
- printf(">> Please unplug the device and restart the program. \n");
- return EXIT_FAILURE;
- }
-
- if (run)
- {
- printf("> Starting the user app ...\n");
- res = micronucleus_startApp(myDevice);
- if(res!=0)
- {
- printf(">> Abort mission! An error has occured ...\n");
- printf(">> Please unplug the device and restart the program. \n");
- return EXIT_FAILURE;
- }
+ } else if (FILE_TYPE_RAW) {
+ if (parseRaw(file, dataBuffer, &startAddress, &endAddress)) {
+ printf("> Error loading raw file.\n");
+ return EXIT_FAILURE;
}
+ }
+
+ printProgress(1.0);
- printf(">> Micronucleus done. Thank you!\n");
-
- return EXIT_SUCCESS;
+ if (startAddress >= endAddress) {
+ printf("> No data in input file, exiting.\n");
+ return EXIT_FAILURE;
+ }
+
+ if (endAddress > my_device->flash_size) {
+ printf("> Program file is %d bytes too big for the bootloader!\n", endAddress - my_device->flash_size);
+ return EXIT_FAILURE;
+ }
+
+ setProgressData("erasing", 4);
+ printf("> Erasing the memory ...\n");
+ res = micronucleus_eraseFlash(my_device, printProgress);
+ if (res != 0) {
+ printf(">> Abort mission! An error has occured ...\n");
+ printf(">> Please unplug the device and restart the program. \n");
+ return EXIT_FAILURE;
+ }
+ printProgress(1.0);
+
+ printf("> Starting to upload ...\n");
+ setProgressData("writing", 5);
+ res = micronucleus_writeFlash(my_device, endAddress, dataBuffer, printProgress);
+ if (res != 0) {
+ printf(">> Abort mission! An error has occured ...\n");
+ printf(">> Please unplug the device and restart the program. \n");
+ return EXIT_FAILURE;
+ }
+
+ if (run) {
+
+ printf("> Starting the user app ...\n");
+ setProgressData("running", 6);
+ printProgress(0.0);
+
+ res = micronucleus_startApp(my_device);
+
+ if (res != 0) {
+ printf(">> Abort mission! An error has occured ...\n");
+ printf(">> Please unplug the device and restart the program. \n");
+ return EXIT_FAILURE;
+ }
+
+ printProgress(1.0);
+ }
+
+ printf(">> Micronucleus done. Thank you!\n");
+
+ return EXIT_SUCCESS;
}
/******************************************************************************/
/******************************************************************************/
-static int parseUntilColon(FILE *fp)
-{
-int c;
+static void printProgress(float progress) {
+ static int last_step;
+
+ if (dump_progress) {
+ printf("status:%s,step:%d,steps:%d,progress:%f\n", progress_friendly_name, progress_step, progress_total_steps, progress);
+ } else {
+ #ifndef WIN
+ if (last_step == progress_step) {
+ printf("\033[1F\033[2K"); // move cursor to previous line and erase last update in this progress sequence
+ }
+ #endif
+ printf("%s: %d%% complete\n", progress_friendly_name, (int) (progress * 100.0f));
+ }
+
+ last_step = progress_step;
+}
- do{
- c = getc(fp);
- }while(c != ':' && c != EOF);
- return c;
+static void setProgressData(char* friendly, int step) {
+ progress_friendly_name = friendly;
+ progress_step = step;
}
/******************************************************************************/
/******************************************************************************/
-static int parseHex(FILE *fp, int numDigits)
-{
-int i;
-char temp[9];
-
- for(i = 0; i < numDigits; i++)
- temp[i] = getc(fp);
- temp[i] = 0;
- return strtol(temp, NULL, 16);
+static int parseUntilColon(FILE *file_pointer) {
+ int character;
+
+ do {
+ character = getc(file_pointer);
+ } while(character != ':' && character != EOF);
+
+ return character;
}
/******************************************************************************/
/******************************************************************************/
-static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAddr)
-{
-int address, base, d, segment, i, lineLen, sum;
-FILE *input;
+static int parseHex(FILE *file_pointer, int num_digits) {
+ int iter;
+ char temp[9];
- input = strcmp(hexfile, "-") == 0 ? stdin : fopen(hexfile, "r");
- if(input == NULL){
- printf("> Error opening %s: %s\n", hexfile, strerror(errno));
- return 1;
- }
- while(parseUntilColon(input) == ':'){
- sum = 0;
- sum += lineLen = parseHex(input, 2);
- base = address = parseHex(input, 4);
- sum += address >> 8;
- sum += address;
- sum += segment = parseHex(input, 2); /* segment value? */
- if(segment != 0) /* ignore lines where this byte is not 0 */
- continue;
- for(i = 0; i < lineLen ; i++){
- d = parseHex(input, 2);
- buffer[address++] = d;
- sum += d;
- }
- sum += parseHex(input, 2);
- if((sum & 0xff) != 0){
- printf("> Warning: Checksum error between address 0x%x and 0x%x\n", base, address);
- }
- if(*startAddr > base)
- *startAddr = base;
- if(*endAddr < address)
- *endAddr = address;
- }
- fclose(input);
- return 0;
+ for(iter = 0; iter < num_digits; iter++) {
+ temp[iter] = getc(file_pointer);
+ }
+ temp[iter] = 0;
+
+ return strtol(temp, NULL, 16);
}
/******************************************************************************/
/******************************************************************************/
-static int parseRaw(char *filename, char* data_buffer, int *start_address, int *end_address) {
- FILE *input;
-
- input = strcmp(filename, "-") == 0 ? stdin : fopen(filename, "r");
+static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAddr) {
+ int address, base, d, segment, i, lineLen, sum;
+ FILE *input;
+
+ input = strcmp(hexfile, "-") == 0 ? stdin : fopen(hexfile, "r");
+ if (input == NULL) {
+ printf("> Error opening %s: %s\n", hexfile, strerror(errno));
+ return 1;
+ }
+
+ while (parseUntilColon(input) == ':') {
+ sum = 0;
+ sum += lineLen = parseHex(input, 2);
+ base = address = parseHex(input, 4);
+ sum += address >> 8;
+ sum += address;
+ sum += segment = parseHex(input, 2); /* segment value? */
+ if (segment != 0) { /* ignore lines where this byte is not 0 */
+ continue;
+ }
- if (input == NULL) {
- printf("> Error reading %s: %s\n", filename, strerror(errno));
- return 1;
+ for (i = 0; i < lineLen; i++) {
+ d = parseHex(input, 2);
+ buffer[address++] = d;
+ sum += d;
}
- *start_address = 0;
- *end_address = 0;
+ sum += parseHex(input, 2);
+ if ((sum & 0xff) != 0) {
+ printf("> Warning: Checksum error between address 0x%x and 0x%x\n", base, address);
+ }
- // read in bytes from file
- int byte = 0;
- while (1) {
- byte = getc(input);
- if (byte == EOF) break;
-
- *data_buffer = byte;
- data_buffer += 1;
- *end_address += 1;
+ if(*startAddr > base) {
+ *startAddr = base;
}
+ if(*endAddr < address) {
+ *endAddr = address;
+ }
+ }
+
+ fclose(input);
+ return 0;
+}
+/******************************************************************************/
+
+/******************************************************************************/
+static int parseRaw(char *filename, char* data_buffer, int *start_address, int *end_address) {
+ FILE *input;
+
+ input = strcmp(filename, "-") == 0 ? stdin : fopen(filename, "r");
+
+ if (input == NULL) {
+ printf("> Error reading %s: %s\n", filename, strerror(errno));
+ return 1;
+ }
+
+ *start_address = 0;
+ *end_address = 0;
+
+ // read in bytes from file
+ int byte = 0;
+ while (1) {
+ byte = getc(input);
+ if (byte == EOF) break;
- fclose(input);
- return 0;
+ *data_buffer = byte;
+ data_buffer += 1;
+ *end_address += 1;
+ }
+
+ fclose(input);
+ return 0;
}
/******************************************************************************/
diff --git a/commandline/library/micronucleus_lib.c b/commandline/library/micronucleus_lib.c
index a719690..2e63425 100644
--- a/commandline/library/micronucleus_lib.c
+++ b/commandline/library/micronucleus_lib.c
@@ -1,24 +1,24 @@
/*
- Created: September 2012
- by ihsan Kehribar <ihsan@kehribar.me>
-
- 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:
+ Created: September 2012
+ by ihsan Kehribar <ihsan@kehribar.me>
+
+ 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 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.
+ 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.
*/
/***************************************************************/
@@ -27,114 +27,120 @@
#include "micronucleus_lib.h"
#include "littleWire_util.h"
-micronucleus* micronucleus_connect()
-{
- micronucleus *nucleus = NULL;
- struct usb_bus *busses;
-
- // intialise usb and find micronucleus device
- usb_init();
- usb_find_busses();
- usb_find_devices();
-
- busses = usb_get_busses();
- struct usb_bus *bus;
- for (bus = busses; bus; bus = bus->next)
- {
- struct usb_device *dev;
-
- for (dev = bus->devices; dev; dev = dev->next)
- {
- /* Check if this device is a micronucleus */
- if (dev->descriptor.idVendor == MICRONUCLEUS_VENDOR_ID && dev->descriptor.idProduct == MICRONUCLEUS_PRODUCT_ID)
- {
- nucleus = malloc(sizeof(micronucleus));
- nucleus->version.major = (dev->descriptor.bcdUSB >> 8) & 0xFF;
- nucleus->version.minor = dev->descriptor.bcdUSB & 0xFF;
- nucleus->device = usb_open(dev);
-
- // get nucleus info
- unsigned char buffer[4];
- int res = usb_control_msg(nucleus->device, 0xC0, 0, 0, 0, buffer, 4, MICRONUCLEUS_USB_TIMEOUT);
- assert(res == 4);
-
- nucleus->flash_size = (buffer[0]<<8) + buffer[1];
- nucleus->page_size = buffer[2];
- nucleus->pages = (nucleus->flash_size / nucleus->page_size);
- if (nucleus->pages * nucleus->page_size < nucleus->flash_size) nucleus->pages += 1;
- nucleus->write_sleep = buffer[3];
- nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages;
- }
- }
- }
+micronucleus* micronucleus_connect() {
+ micronucleus *nucleus = NULL;
+ struct usb_bus *busses;
+
+ // intialise usb and find micronucleus device
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ busses = usb_get_busses();
+ struct usb_bus *bus;
+ for (bus = busses; bus; bus = bus->next) {
+ struct usb_device *dev;
+
+ for (dev = bus->devices; dev; dev = dev->next) {
+ /* Check if this device is a micronucleus */
+ if (dev->descriptor.idVendor == MICRONUCLEUS_VENDOR_ID && dev->descriptor.idProduct == MICRONUCLEUS_PRODUCT_ID) {
+ nucleus = malloc(sizeof(micronucleus));
+ nucleus->version.major = (dev->descriptor.bcdUSB >> 8) & 0xFF;
+ nucleus->version.minor = dev->descriptor.bcdUSB & 0xFF;
+ nucleus->device = usb_open(dev);
+
+ // get nucleus info
+ unsigned char buffer[4];
+ int res = usb_control_msg(nucleus->device, 0xC0, 0, 0, 0, buffer, 4, MICRONUCLEUS_USB_TIMEOUT);
+ assert(res == 4);
+
+ nucleus->flash_size = (buffer[0]<<8) + buffer[1];
+ nucleus->page_size = buffer[2];
+ nucleus->pages = (nucleus->flash_size / nucleus->page_size);
+ if (nucleus->pages * nucleus->page_size < nucleus->flash_size) nucleus->pages += 1;
+ nucleus->write_sleep = buffer[3];
+ nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages;
+ }
+ }
+ }
- return nucleus;
+ return nucleus;
}
-int micronucleus_eraseFlash(micronucleus* deviceHandle)
-{
- int res;
- res = usb_control_msg(deviceHandle->device, 0xC0, 2, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT);
-
- // give microcontroller enough time to erase all writable pages and come back online
- delay(deviceHandle->erase_sleep);
-
- if(res!=0)
- return -1;
- else
- return 0;
+int micronucleus_eraseFlash(micronucleus* deviceHandle, micronucleus_callback progress) {
+ int res;
+ res = usb_control_msg(deviceHandle->device, 0xC0, 2, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT);
+
+ // give microcontroller enough time to erase all writable pages and come back online
+ float i = 0;
+ while (i < 1.0) {
+ // update progress callback if one was supplied
+ if (progress) progress(i);
+
+ delay(((float) deviceHandle->erase_sleep) / 100.0f);
+ i += 0.01;
+ }
+
+ if(res!=0)
+ return -1;
+ else
+ return 0;
}
-int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_size, unsigned char* program)
-{
- unsigned char page_length = deviceHandle->page_size;
- unsigned char page_buffer[page_length];
- unsigned int address; // overall flash memory address
- unsigned int page_address; // address within this page when copying buffer
- unsigned int res;
+int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_size, unsigned char* program, micronucleus_callback prog) {
+ unsigned char page_length = deviceHandle->page_size;
+ unsigned char page_buffer[page_length];
+ unsigned int address; // overall flash memory address
+ unsigned int page_address; // address within this page when copying buffer
+ unsigned int res;
- for (address = 0; address < deviceHandle->flash_size; address += deviceHandle->page_size) {
- // work around a bug in older bootloader versions
- if (deviceHandle->version.major == 1 && deviceHandle->version.minor <= 2
- && address / deviceHandle->page_size == deviceHandle->pages - 1) {
- page_length = deviceHandle->flash_size % deviceHandle->page_size;
- }
-
- // copy in bytes from user program
- for (page_address = 0; page_address < page_length; page_address += 1) {
- if (address + page_address > program_size) {
- page_buffer[page_address] = 0xFF; // pad out remainder with unprogrammed bytes
- } else {
- page_buffer[page_address] = program[address + page_address]; // load from user program
- }
- }
-
- // ask microcontroller to write this page's data
- res = usb_control_msg(deviceHandle->device,
- USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 1,
- page_length, address,
- page_buffer, page_length,
- MICRONUCLEUS_USB_TIMEOUT);
-
- // give microcontroller enough time to write this page and come back online
- delay(deviceHandle->write_sleep);
-
- if (res != 64) return -1;
- }
-
- return 0;
+ for (address = 0; address < deviceHandle->flash_size; address += deviceHandle->page_size) {
+ // work around a bug in older bootloader versions
+ if (deviceHandle->version.major == 1 && deviceHandle->version.minor <= 2
+ && address / deviceHandle->page_size == deviceHandle->pages - 1) {
+ page_length = deviceHandle->flash_size % deviceHandle->page_size;
+ }
+
+ // copy in bytes from user program
+ for (page_address = 0; page_address < page_length; page_address += 1) {
+ if (address + page_address > program_size) {
+ page_buffer[page_address] = 0xFF; // pad out remainder with unprogrammed bytes
+ } else {
+ page_buffer[page_address] = program[address + page_address]; // load from user program
+ }
+ }
+
+ // ask microcontroller to write this page's data
+ res = usb_control_msg(deviceHandle->device,
+ USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 1,
+ page_length, address,
+ page_buffer, page_length,
+ MICRONUCLEUS_USB_TIMEOUT);
+
+ // call progress update callback if that's a thing
+ if (prog) prog(((float) address) / ((float) deviceHandle->flash_size));
+
+ // give microcontroller enough time to write this page and come back online
+ delay(deviceHandle->write_sleep);
+
+ if (res != 64) return -1;
+ }
+
+ // call progress update callback with completion status
+ if (prog) prog(1.0);
+
+ return 0;
}
-int micronucleus_startApp(micronucleus* deviceHandle)
-{
- int res;
- res = usb_control_msg(deviceHandle->device, 0xC0, 4, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT);
-
- if(res!=0)
- return -1;
- else
- return 0;
+int micronucleus_startApp(micronucleus* deviceHandle) {
+ int res;
+ res = usb_control_msg(deviceHandle->device, 0xC0, 4, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT);
+
+ if(res!=0)
+ return -1;
+ else
+ return 0;
}
diff --git a/commandline/library/micronucleus_lib.h b/commandline/library/micronucleus_lib.h
index dcbac83..d022877 100644
--- a/commandline/library/micronucleus_lib.h
+++ b/commandline/library/micronucleus_lib.h
@@ -2,46 +2,46 @@
#define MICRONUCLEUS_LIB_H
/*
- Created: September 2012
- by ihsan Kehribar <ihsan@kehribar.me>
-
- 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:
+ Created: September 2012
+ by ihsan Kehribar <ihsan@kehribar.me>
+
+ 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 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.
+ 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.
*/
/********************************************************************************
* Header files
********************************************************************************/
#if defined WIN
- #include <lusb0_usb.h> // this is libusb, see http://libusb.sourceforge.net/
+ #include <lusb0_usb.h> // this is libusb, see http://libusb.sourceforge.net/
#else
- #include <usb.h> // this is libusb, see http://libusb.sourceforge.net/
+ #include <usb.h> // this is libusb, see http://libusb.sourceforge.net/
#endif
-//#include "opendevice.h" // common code moved to separate module
+//#include "opendevice.h" // common code moved to separate module
#include <assert.h>
/*******************************************************************************/
/********************************************************************************
* USB details
********************************************************************************/
-#define MICRONUCLEUS_VENDOR_ID 0x16D0
-#define MICRONUCLEUS_PRODUCT_ID 0x0753
-#define MICRONUCLEUS_USB_TIMEOUT 0xFFFF
+#define MICRONUCLEUS_VENDOR_ID 0x16D0
+#define MICRONUCLEUS_PRODUCT_ID 0x0753
+#define MICRONUCLEUS_USB_TIMEOUT 0xFFFF
/*******************************************************************************/
/********************************************************************************
@@ -50,22 +50,24 @@
//typedef usb_dev_handle micronucleus;
// representing version number of micronucleus device
typedef struct _micronucleus_version {
- unsigned char major;
- unsigned char minor;
+ unsigned char major;
+ unsigned char minor;
} micronucleus_version;
// handle representing one micronucleus device
typedef struct _micronucleus {
- usb_dev_handle *device;
- // general information about device
- micronucleus_version version;
- unsigned int flash_size; // programmable size (in bytes) of progmem
- unsigned int page_size; // size (in bytes) of page
- unsigned int pages; // total number of pages to program
- unsigned int write_sleep; // milliseconds
- unsigned int erase_sleep; // milliseconds
+ usb_dev_handle *device;
+ // general information about device
+ micronucleus_version version;
+ unsigned int flash_size; // programmable size (in bytes) of progmem
+ unsigned int page_size; // size (in bytes) of page
+ unsigned int pages; // total number of pages to program
+ unsigned int write_sleep; // milliseconds
+ unsigned int erase_sleep; // milliseconds
} micronucleus;
+typedef void (*micronucleus_callback)(float progress);
+
/*******************************************************************************/
/********************************************************************************
@@ -78,13 +80,14 @@ micronucleus* micronucleus_connect();
/********************************************************************************
* Erase the flash memory
********************************************************************************/
-int micronucleus_eraseFlash(micronucleus* deviceHandle);
+int micronucleus_eraseFlash(micronucleus* deviceHandle, micronucleus_callback progress);
/*******************************************************************************/
/********************************************************************************
* Write the flash memory
********************************************************************************/
-int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_length, unsigned char* program);
+int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_length,
+ unsigned char* program, micronucleus_callback progress);
/*******************************************************************************/
/********************************************************************************