diff --git a/keywords.txt b/keywords.txt index 63d9865..afbded0 100644 --- a/keywords.txt +++ b/keywords.txt @@ -47,6 +47,7 @@ drawSlowXYBitmap KEYWORD2 drawTriangle KEYWORD2 enabled KEYWORD2 everyXFrames KEYWORD2 +exitToBootloader KEYWORD2 fillCircle KEYWORD2 fillRect KEYWORD2 fillRoundRect KEYWORD2 @@ -68,6 +69,7 @@ initRandomSeed KEYWORD2 invert KEYWORD2 justPressed KEYWORD2 justReleased KEYWORD2 +mainNoUSB KEYWORD2 nextFrame KEYWORD2 nextFrameDEV KEYWORD2 notPressed KEYWORD2 diff --git a/src/Arduboy2Core.cpp b/src/Arduboy2Core.cpp index cb6167a..93d3cc1 100644 --- a/src/Arduboy2Core.cpp +++ b/src/Arduboy2Core.cpp @@ -476,3 +476,73 @@ void Arduboy2Core::delayShort(uint16_t ms) delay((unsigned long) ms); } +// reset to the bootloader using the watchdog timer +void Arduboy2Core::exitToBootloader() +{ + // prevent the bootloader magic number from being overwritten by timer 0 + // when a timer variable overlaps the magic number location. + power_timer0_disable(); + + *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY; + wdt_enable(WDTO_15MS); + + while (true) { } +} + +void Arduboy2Core::mainNoUSB() +{ + init(); + + // disable USB + UDCON = _BV(DETACH); + USBCON = _BV(FRZCLK); + power_usb_disable(); + +#ifdef ARDUBOY_10 + // Set the UP button pin for INPUT_PULLUP + PORTF |= _BV(UP_BUTTON_BIT); + DDRF &= ~(_BV(UP_BUTTON_BIT)); + + // Set RGB led to magenta + PORTB |= _BV(GREEN_LED_BIT); // green off (high) + PORTB &= ~(_BV(RED_LED_BIT)); // red on (low) + PORTB &= ~(_BV(BLUE_LED_BIT)); // blue on (low) + // set RGB led pins as outputs + DDRB |= _BV(RED_LED_BIT) | _BV(GREEN_LED_BIT) | _BV(BLUE_LED_BIT); + + // Delay to give time for the UP pin to be pulled high if it was floating + for (volatile uint8_t i = 0; i < 100; i++) { } + + // if the UP button is pressed + if ((PINF & _BV(UP_BUTTON_BIT)) == 0) { + exitToBootloader(); + } +#elif defined(AB_DEVKIT) +//TODO do above for DevKit (light the blue LED) +#endif + + // The remainder is a copy of the Arduino main() function with the + // USB code and other unneeded code commented out. + // init() was called above. + // The call to function initVariant() is commented out to fix compiler + // error: "multiple definition of 'main'". + // The return statment is removed since this function is type void. + +// init(); + +// initVariant(); + +//#if defined(USBCON) +// USBDevice.attach(); +//#endif + + setup(); + + for (;;) { + loop(); +// if (serialEventRun) serialEventRun(); + } + +// return 0; +} + diff --git a/src/Arduboy2Core.h b/src/Arduboy2Core.h index 324ae15..ad9746d 100644 --- a/src/Arduboy2Core.h +++ b/src/Arduboy2Core.h @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -689,6 +690,22 @@ class Arduboy2Core */ void static delayShort(uint16_t ms) __attribute__ ((noinline)); + /** \brief + * Exit the sketch and start the bootloader + * + * \details + * TODO add details including cautions and warnings + */ + void static exitToBootloader(); + + /** \brief + * Arduino main() function without USB + * + * \details + * TODO add details including cautions and warnings + */ + void static mainNoUSB(); + protected: // internals void static setCPUSpeed8MHz();