From 84d1014b14687f08fe866825d2f024850f875715 Mon Sep 17 00:00:00 2001 From: "Mr.Blinky" <4971163+MrBlinky@users.noreply.github.com> Date: Sat, 27 Jun 2020 01:29:56 +0200 Subject: [PATCH] update arduboy core updated arduboy optimized core with Arduino core changes wiring.c: optimized timer ISR by removing power down and button counters for shorter and faster code --- board-package-source/cores/arduboy/Arduino.h | 28 +- board-package-source/cores/arduboy/CDC.cpp | 33 +- board-package-source/cores/arduboy/Stream.cpp | 1 - board-package-source/cores/arduboy/USBAPI.h | 2 + .../cores/arduboy/USBCore.cpp | 9 +- board-package-source/cores/arduboy/USBCore.h | 5 +- .../cores/arduboy/WInterrupts.c | 85 +++- .../cores/arduboy/WString.cpp | 2 +- board-package-source/cores/arduboy/abi.cpp | 4 +- board-package-source/cores/arduboy/new.cpp | 5 + board-package-source/cores/arduboy/new.h | 1 + board-package-source/cores/arduboy/wiring.c | 383 ++++++++---------- .../cores/arduboy/wiring_shift.c | 11 +- 13 files changed, 288 insertions(+), 281 deletions(-) diff --git a/board-package-source/cores/arduboy/Arduino.h b/board-package-source/cores/arduboy/Arduino.h index ccff4a3..979c3f8 100644 --- a/board-package-source/cores/arduboy/Arduino.h +++ b/board-package-source/cores/arduboy/Arduino.h @@ -113,7 +113,8 @@ void yield(void); #define bitRead(value, bit) (((value) >> (bit)) & 0x01) #define bitSet(value, bit) ((value) |= (1UL << (bit))) #define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) +#define bitToggle(value, bit) ((value) ^= (1UL << (bit))) +#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit)) // avr-libc defines _NOP() since 1.6.2 #ifndef _NOP @@ -127,29 +128,22 @@ typedef unsigned int word; typedef bool boolean; typedef uint8_t byte; -//volatile unsigned char button_ticks_hold; // millis >> 8 when bootloader/reset combo buttons is pressed -//volatile unsigned char button_ticks_now; // millis >> 12 -//volatile unsigned char button_ticks_last; // millis >> 12 of last button pressedd -//volatile unsigned char frame_ticks; // sychronized with millis - void init(void); void initVariant(void); int atexit(void (*func)()) __attribute__((weak)); -void pinMode(uint8_t, uint8_t); -void digitalWrite(uint8_t, uint8_t); -int digitalRead(uint8_t); -int analogRead(uint8_t); +void pinMode(uint8_t pin, uint8_t mode); +void digitalWrite(uint8_t pin, uint8_t val); +int digitalRead(uint8_t pin); +int analogRead(uint8_t pin); void analogReference(uint8_t mode); -void analogWrite(uint8_t, int); +void analogWrite(uint8_t pin, int val); -unsigned char buttonsIdleTime(void); -unsigned char millisChar(void); unsigned long millis(void); unsigned long micros(void); -void delay(unsigned long); -void delayShort(unsigned short); +void delay(unsigned long ms); +void delayShort(unsigned short ms); void delayMicroseconds(unsigned int us); unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout); @@ -157,8 +151,8 @@ unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout); void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); -void attachInterrupt(uint8_t, void (*)(void), int mode); -void detachInterrupt(uint8_t); +void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode); +void detachInterrupt(uint8_t interruptNum); void setup(void); void loop(void); diff --git a/board-package-source/cores/arduboy/CDC.cpp b/board-package-source/cores/arduboy/CDC.cpp index 15b3e70..c52739f 100644 --- a/board-package-source/cores/arduboy/CDC.cpp +++ b/board-package-source/cores/arduboy/CDC.cpp @@ -18,7 +18,6 @@ #include "USBAPI.h" #include -#include #include #if defined(USBCON) @@ -35,18 +34,14 @@ typedef struct static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; static volatile int32_t breakValue = -1; -#ifndef ARDUBOY_CORE static u8 wdtcsr_save; -#else -extern volatile unsigned char bootloader_timer; -#endif #define WEAK __attribute__ ((weak)) extern const CDCDescriptor _cdcInterface PROGMEM; const CDCDescriptor _cdcInterface = { - D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), // CDC communication interface D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), @@ -107,33 +102,31 @@ bool CDC_Setup(USBSetup& setup) // open at 1200 bps, is closed. this is the signal to start the watchdog // with a relatively long period so it can finish housekeeping tasks // like servicing endpoints before the sketch ends -#ifndef ARDUBOY_CORE + uint16_t magic_key_pos = MAGIC_KEY_POS; // If we don't use the new RAMEND directly, check manually if we have a newer bootloader. // This is used to keep compatible with the old leonardo bootloaders. // You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check. - #if MAGIC_KEY_POS != (RAMEND-1) +#if MAGIC_KEY_POS != (RAMEND-1) // For future boards save the key in the inproblematic RAMEND // Which is reserved for the main() return value (which will never return) if (isLUFAbootloader()) { // horray, we got a new bootloader! magic_key_pos = (RAMEND-1); } - #endif #endif // We check DTR state to determine if host port is open (bit 0 of lineState). if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) -#ifndef ARDUBOY_CORE { - #if MAGIC_KEY_POS != (RAMEND-1) - // Backup ram value if its not a newer bootloader. +#if MAGIC_KEY_POS != (RAMEND-1) + // Backup ram value if its not a newer bootloader and it hasn't already been saved. // This should avoid memory corruption at least a bit, not fully if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) { *(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos; } - #endif +#endif // Store boot key *(uint16_t *)magic_key_pos = MAGIC_KEY; // Save the watchdog state in case the reset is aborted. @@ -153,27 +146,17 @@ bool CDC_Setup(USBSetup& setup) // Restore the watchdog state in case the sketch was using it. WDTCSR |= (1< 0 ? true : false); } @@ -855,4 +854,10 @@ bool USBDevice_::wakeupHost() return false; } +bool USBDevice_::isSuspended() +{ + return (_usbSuspendState & (1 << SUSPI)); +} + + #endif /* if defined(USBCON) */ diff --git a/board-package-source/cores/arduboy/USBCore.h b/board-package-source/cores/arduboy/USBCore.h index 4210ced..0c63c2b 100644 --- a/board-package-source/cores/arduboy/USBCore.h +++ b/board-package-source/cores/arduboy/USBCore.h @@ -97,6 +97,9 @@ // bMaxPower in Configuration Descriptor #define USB_CONFIG_POWER_MA(mA) ((mA)/2) +#ifndef USB_CONFIG_POWER + #define USB_CONFIG_POWER (500) +#endif // bEndpointAddress in Endpoint Descriptor #define USB_ENDPOINT_DIRECTION_MASK 0x80 @@ -267,7 +270,7 @@ typedef struct { 18, 1, USB_VERSION, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } #define D_CONFIG(_totalLength,_interfaces) \ - { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(500) } + { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(USB_CONFIG_POWER) } #define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } diff --git a/board-package-source/cores/arduboy/WInterrupts.c b/board-package-source/cores/arduboy/WInterrupts.c index cef1106..38ea158 100644 --- a/board-package-source/cores/arduboy/WInterrupts.c +++ b/board-package-source/cores/arduboy/WInterrupts.c @@ -65,7 +65,6 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = { nothing, #endif }; -// volatile static voidFuncPtr twiIntFunc; void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { @@ -103,6 +102,39 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { EICRB = (EICRB & ~((1< -extern "C" void __cxa_pure_virtual(void) __attribute__ ((__naked__)); -extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__naked__)); +extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); +extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); void __cxa_pure_virtual(void) { // We might want to write some diagnostics to uart in this case diff --git a/board-package-source/cores/arduboy/new.cpp b/board-package-source/cores/arduboy/new.cpp index cf6f89c..fc30cf8 100644 --- a/board-package-source/cores/arduboy/new.cpp +++ b/board-package-source/cores/arduboy/new.cpp @@ -26,6 +26,11 @@ void *operator new[](size_t size) { return malloc(size); } +void * operator new(size_t size, void * ptr) noexcept { + (void)size; + return ptr; +} + void operator delete(void * ptr) { free(ptr); } diff --git a/board-package-source/cores/arduboy/new.h b/board-package-source/cores/arduboy/new.h index 6e1b68f..763f5cc 100644 --- a/board-package-source/cores/arduboy/new.h +++ b/board-package-source/cores/arduboy/new.h @@ -23,6 +23,7 @@ void * operator new(size_t size); void * operator new[](size_t size); +void * operator new(size_t size, void * ptr) noexcept; void operator delete(void * ptr); void operator delete[](void * ptr); diff --git a/board-package-source/cores/arduboy/wiring.c b/board-package-source/cores/arduboy/wiring.c index e89e3f3..477d4e8 100644 --- a/board-package-source/cores/arduboy/wiring.c +++ b/board-package-source/cores/arduboy/wiring.c @@ -20,8 +20,6 @@ Boston, MA 02111-1307 USA */ -#define ARDUBOY_CORE_WIRING_C - #include "wiring_private.h" // the prescaler is set so that timer0 ticks every 64 clock cycles, and the @@ -42,191 +40,150 @@ volatile unsigned long timer0_millis = 0; static unsigned char timer0_fract = 0; volatile unsigned char button_ticks_hold = 0; -volatile unsigned char button_ticks_now = 0; -volatile unsigned char button_ticks_last = 0; -volatile unsigned char bootloader_timer = 0; #if defined(TIM0_OVF_vect) -ISR(TIM0_OVF_vect) +ISR(TIM0_OVF_vect, ISR_NAKED) #else ISR(TIMER0_OVF_vect, ISR_NAKED) #endif { - // copy these to local variables so they can be stored in registers - // (volatile variables must be read from memory on every access) -/* - unsigned long m = timer0_millis; - unsigned char f = timer0_fract; +/* + // copy these to local variables so they can be stored in registers + // (volatile variables must be read from memory on every access) + unsigned long m = timer0_millis; + unsigned char f = timer0_fract; - m += MILLIS_INC; - f += FRACT_INC; - if (f >= FRACT_MAX) { - f -= FRACT_MAX; - m += 1; - } + m += MILLIS_INC; + f += FRACT_INC; + if (f >= FRACT_MAX) { + f -= FRACT_MAX; + m += 1; + } + timer0_fract = f; + timer0_millis = m; + timer0_overflow_count++; + + assembly optimisation saves 46 bytes compared to compiled C++ version + by adding arduboy button combo code takes 8 bytes more than C++ version + 3 bytes ram saved (1 byte used extra for button_ticks_hold but 4 bytes + saved due to less stack pushes) +*/ + asm volatile( + // save registers and SREG before 12622 after 12576 (saving 46 bytes) + " push r0 \n" + " in r0, __SREG__ \n" + " push r24 \n" + " push r25 \n" + " push r30 \n" + " push r31 \n" + " ldi r25, - %[millis_inc] \n" // millis_inc = MILLIS_INC; + " lds r24, %[fract] \n" // f= timer0_fract; + " subi r24, - %[fract_inc] \n" // f += FRACT_INC; + " cpi r24, %[fract_max] \n" // if (f >= FRACT_MAX) + " brcs 1f \n" // { - timer0_fract = f; - timer0_millis = m; - timer0_overflow_count++; -*/ - // save registers and SREG - asm volatile( - " push r16 \n\t" - " in r16, __SREG__ \n\t" - " push r16 \n\t" //use as more functional temp reg - " push r1 \n\t" - " clr r1 \n\t" //zero reg - " push r24 \n\t" - " push r25 \n\t" - " push r30 \n\t" - " push r31 \n\t" - ); - asm volatile( - " lds r24, %[fract] \n\t" // f= timer0_fract; - " ldi r25, %[millis_inc] \n\t" // millis_inc = MILLIS_INC; - " subi r24, %[fract_inc] \n\t" // f += FRACT_INC; - " cpi r24, %[fract_max] \n\t" // if (f >= FRACT_MAX) { - " brcs 1f \n\t" - - " subi r24, %[fract_max] \n\t" // f -= FRACT_MAX; - " inc r25 \n\t" // millis_inc++ } - "1: \n\t" - " sts %[fract], r24 \n\t" // timer0_fract = f; - " ld r24, z \n\t" //timer0_millis += millis_inc - " add r24, r25 \n\t" - " st z, r24 \n\t" - " ldd r25, z+1 \n\t" - " adc r25, r1 \n\t" - " std z+1, r25 \n\t" // r25 = (millis >>8) - " ldd r16, z+2 \n\t" - " adc r16, r1 \n\t" - " std z+2, r16 \n\t" // r16 = (millis >>16) - " ldd r24, z+3 \n\t" - " adc r24, r1 \n\t" - " std z+3, r24 \n\t" - - " eor r16, r25 \n\t" //button_ticks_now = (millis >> 12) - " andi r16, 0x0F \n\t" - " eor r16, r25 \n\t" - " swap r16 \n\t" - " sts %[buttons_now], r16 \n\t" - : - : [millis] "z" (&timer0_millis), - [fract] "" (&timer0_fract), - [buttons_now] "" (&button_ticks_now), - [millis_inc] "M" (MILLIS_INC), - [fract_inc] "M" (256 - FRACT_INC), // negated for subi instruction - [fract_max] "M" (FRACT_MAX) - : - ); - //Arduboy bootloader and reset button feature - asm volatile ( - " rcall scan_buttons \n\t" - " cpse r24, r1 \n\t" //if (buttons) button_ticks_last = (uint8_t)(Millis >> 12) - " sts %[apd], r16 \n\t" -#ifdef AB_DEVKIT - " cpi r24, 0x50 \n\t" // test DevKit UP+DOWN for bootloader -#else - " cpi r24, 0x90 \n\t" // test arduboy UP+DOWN for bootloader -#endif - " brne 5f \n\t" - "2: lds r16, %[hold] \n\t" - " sub r25, r16 \n\t" // (uint8_t)(timer0_millis >> 8) - button_ticks_last - " cpi r25, 6 \n\t" - " brcs 6f \n\t" // if ((millis - hold) >= 6) { - "3: ldi r24, 0x77 \n\t" - " sts 0x800, r24 \n\t" - " sts 0x801, r24 \n\t" - " ldi r24, %[value1] \n\t" - " ldi r25, %[value2] \n\t" - " sts %[wdtcsr], r24 \n\t" - " sts %[wdtcsr], r25 \n\t" - " rjmp .-2 \n\t" // } - "5: \n\t" - " sts %[hold], r25 \n\t" //button_ticks_hold = (uint8_t)(Millis >> 8) - "6: \n\t" - " lds r24, %[btimer] \n\t" //if (bootloader_timer--) { - " subi r24, 1 \n\t" - " brcs 7f \n\t" - " sts %[btimer],r24 \n\t" - " breq 3b \n\t" // if (bootloader_timer == 0) runBootLoader; - "7: \n\t" //} + " subi r24, %[fract_max] \n" // f -= FRACT_MAX; + " dec r25 \n" // millis_inc++ + "1: \n" // } + " sts %[fract], r24 \n" // timer0_fract = f; + // timer0_millis += millis_inc (addition by substracting negative value) + " ldi r30, lo8(%[millis]) \n" + " ldi r31, hi8(%[millis]) \n" + " ld r24, z \n" + " sub r24, r25 \n" + " st z, r24 \n" + " ldd r25, z+1 \n" + " sbci r25, 0xFF \n" // save (uint8_t)(timer0_millis >> 8) in 25 + " std z+1, r25 \n" + " ldd r24, z+2 \n" + " sbci r24, 0xFF \n" + " std z+2, r24 \n" + " ldd r24, z+3 \n" + " sbci r24, 0xFF \n" + " std z+3, r24 \n" + //timer0_overflow_count++; + " ldi r30, lo8(%[count]) \n" + " ldi r31, hi8(%[count]) \n" + " ld r24, z \n" + " subi r24, 0xFF \n" // ++ (addition by substracting negative value) + " st z, r24 \n" + " ldd r24, z+1 \n" + " sbci r24, 0xFF \n" + " std z+1, r24 \n" + " ldd r24, z+2 \n" + " sbci r24, 0xFF \n" + " std z+2, r24 \n" + " ldd r24, z+3 \n" + " sbci r24, 0xFF \n" + " std z+3, r24 \n" + //read Arduboy buttons +#ifdef AB_DEVKIT + " in r24, %[pinb] \n" // down, left, up buttons + " andi r24, 0x8F \n" + " sbis %[pinc], 6 \n" // right button + " andi r24, 0xFB \n" + " sbis %[pinf], 7 \n" // A button + " andi r24, 0xFD \n" + " sbis %[pinf], 6 \n" // B button + " andi r24, 0xFE \n" + " cpi r24, 0xAF \n" // test DevKit UP+DOWN for bootloader +#else + " in r24, %[pinf] \n" // directional buttons + " ori r24, 0x0F \n" + " sbis %[pine], 6 \n" // A button + " andi r24, 0xF7 \n" + " sbis %[pinb], 4 \n" // B button + " andi r24, 0xFB \n" + " cpi r24, 0x6F \n" // test arduboy UP+DOWN for bootloader +#endif + " brne 5f \n" // skip button combo not pressed + // test button combo hold long enough + "2: lds r24, %[hold] \n" + " sub r25, r24 \n" // (uint8_t)(timer0_millis >> 8) - button_ticks_hold + " cpi r25, 6 \n" // 1536ms >> 8 + " brcs 6f \n" // skip not long enough + //button combo pressed long enough: trigger bootloader mode + ".global exit_to_bootloader \n" + "exit_to_bootloader: \n" + "3: ldi r24, 0x77 \n" // set bootloader MAGIC KEY + " sts 0x800, r24 \n" + " sts 0x801, r24 \n" + " ldi r24, %[value1] \n" // set watchdog timer + " ldi r25, %[value2] \n" + " sts %[wdtcsr], r24 \n" + " sts %[wdtcsr], r25 \n" + " rjmp .-2 \n" // infinite loop will trigger watchdog reset + "5: \n" // } + // reset button_ticks_hold + " sts %[hold], r25 \n" // button_ticks_hold = (uint8_t)(Millis >> 8) + "6: \n" + //restore registers and return from interrupt + " pop r31 \n" + " pop r30 \n" + " pop r25 \n" + " pop r24 \n" + " out __SREG__, r0 \n" + " pop r0 \n" + " reti \n" : - : [hold] "" (&button_ticks_hold), - [apd] "" (&button_ticks_last), - [btimer] "" (&bootloader_timer), + : [millis] "" (&timer0_millis), + [fract] "" (&timer0_fract), + [millis_inc] "M" (MILLIS_INC), + [fract_inc] "M" (FRACT_INC), + [fract_max] "M" (FRACT_MAX), + [count] "" (&timer0_overflow_count), + [hold] "" (&button_ticks_hold), + [pinf] "I" (_SFR_IO_ADDR(PINF)), + [pine] "I" (_SFR_IO_ADDR(PINE)), + [pinc] "I" (_SFR_IO_ADDR(PINC)), + [pinb] "I" (_SFR_IO_ADDR(PINB)), [value1] "M" ((uint8_t)(_BV(WDCE) | _BV(WDE))), [value2] "M" ((uint8_t)(_BV(WDE))), [wdtcsr] "M" (_SFR_MEM_ADDR(WDTCSR)) - : - ); - //timer0_overflow_count++; - asm volatile ( - " ld r24, z \n\t" - " ldd r25, z+1 \n\t" - " adiw r24, 1 \n\t" - " st z, r24 \n\t" - " std z+1, r25 \n\t" - " ldd r24, z+2 \n\t" - " ldd r25, z+3 \n\t" - " adc r24, r1 \n\t" - " adc r25, r1 \n\t" - " std z+2, r24 \n\t" - " std z+3, r25 \n\t" - : - : "z" (&timer0_overflow_count) - ); - //restore registers and retirn from interrupt - asm volatile ( - " pop r31 \n\t" - " pop r30 \n\t" - " pop r25 \n\t" - " pop r24 \n\t" - " pop r1 \n\t" - " pop r16 \n\t" - " out __SREG__, r16 \n\t" - " pop r16 \n\t" - " reti \n\t" - ".global scan_buttons \n\t" - "scan_buttons: \n\t" -#ifdef AB_DEVKIT - " in r24, %[pinb] \n\t" // down, left, up buttons - " com r24 \n\t" - " andi r24, 0x70 \n\t" - " sbis %[pinc], 6 \n\t" // right button - " ori r24, 0x04 \n\t" - " sbis %[pinf], 7 \n\t" // A button - " ori r24, 0x02 \n\t" - " sbis %[pinf], 6 \n\t" // B button - " ori r24, 0x01 \n\t" -#else - " in r24, %[pinf] \n\t" // directional buttons - " com r24 \n\t" - " andi r24, 0xF0 \n\t" - " sbis %[pine], 6 \n\t" // A button - " ori r24, 0x08 \n\t" - " sbis %[pinb], 4 \n\t" // B button - " ori r24, 0x04 \n\t" -#endif - " ret \n\t" // Z flag set from AND when no button is pressed : - : [pinf] "I" (_SFR_IO_ADDR(PINF)), - [pine] "I" (_SFR_IO_ADDR(PINE)), - [pinc] "I" (_SFR_IO_ADDR(PINC)), - [pinb] "I" (_SFR_IO_ADDR(PINB)) ); } -unsigned char buttonsIdleTime() -{ - return button_ticks_now - button_ticks_last; -} - -unsigned char millisChar() -{ - return *(unsigned char*)&timer0_millis; -} - unsigned long millis() { unsigned long m; @@ -428,9 +385,9 @@ void delayMicroseconds(unsigned int us) // for a one-microsecond delay, simply return. the overhead // of the function call takes 18 (20) cycles, which is 1us __asm__ __volatile__ ( - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" + "nop" "\n" + "nop" "\n" + "nop" "\n" "nop"); //just waiting 4 cycles if (us <= 1) return; // = 3 cycles, (4 when true) @@ -514,7 +471,7 @@ void delayMicroseconds(unsigned int us) // busy wait __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles + "1: sbiw %0,1" "\n" // 2 cycles "brne 1b" : "=w" (us) : "0" (us) // 2 cycles ); // return = 4 cycles @@ -533,8 +490,8 @@ void init() //assembly optimized by 68 bytes //sbi(TCCR0A, WGM01); //sbi(TCCR0A, WGM00); asm volatile( - " ldi r24, %[value] \n\t" - " out %[tccr0a], r24 \n\t" + " ldi r24, %[value] \n" + " out %[tccr0a], r24 \n" : : [tccr0a] "I" (_SFR_IO_ADDR(TCCR0A)), [value] "M" (_BV(WGM01) | _BV(WGM00)) @@ -555,8 +512,8 @@ void init() //assembly optimized by 68 bytes //sbi(TCCR0B, CS01); //sbi(TCCR0B, CS00); asm volatile( - " ldi r24, %[value] \n\t" - " out %[tccr0b], r24 \n\t" + " ldi r24, %[value] \n" + " out %[tccr0b], r24 \n" : : [tccr0b] "I" (_SFR_IO_ADDR(TCCR0B)), [value] "M" (_BV(CS01) | _BV(CS00)) @@ -593,10 +550,10 @@ void init() //assembly optimized by 68 bytes //sbi(TCCR1B, CS10); //#endif asm volatile( - " ldi r30, %[tccr1b] \n\t" - " ldi r31, 0x00 \n\t" - " ldi r24, %[value] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr1b] \n" + " ldi r31, 0x00 \n" + " ldi r24, %[value] \n" + " st z, r24 \n" : : [tccr1b] "M" (_SFR_MEM_ADDR(TCCR1B)), #if F_CPU >= 8000000L @@ -617,9 +574,9 @@ void init() //assembly optimized by 68 bytes #if defined(TCCR1A) && defined(WGM10) //sbi(TCCR1A, WGM10); asm volatile( - " ldi r30, %[tccr1a] \n\t" - " ldi r24, %[wgm10] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr1a] \n" + " ldi r24, %[wgm10] \n" + " st z, r24 \n" : : [tccr1a] "M" (_SFR_MEM_ADDR(TCCR1A)), [wgm10] "M" (_BV(WGM10)) @@ -649,9 +606,9 @@ void init() //assembly optimized by 68 bytes //sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64 //sbi(TCCR3B, CS30); asm volatile( - " ldi r30, %[tccr3b] \n\t" - " ldi r24, %[value] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr3b] \n" + " ldi r24, %[value] \n" + " st z, r24 \n" : : [tccr3b] "M" (_SFR_MEM_ADDR(TCCR3B)), [value] "M" (_BV(CS31) | _BV(CS30)) @@ -659,9 +616,9 @@ void init() //assembly optimized by 68 bytes ); //sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode asm volatile( - " ldi r30, %[tccr3a] \n\t" - " ldi r24, %[wgm30] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr3a] \n" + " ldi r24, %[wgm30] \n" + " st z, r24 \n" : : [tccr3a] "M" (_SFR_MEM_ADDR(TCCR3A)), [wgm30] "M" (_BV(WGM30)) @@ -674,9 +631,9 @@ void init() //assembly optimized by 68 bytes //sbi(TCCR4B, CS41); //sbi(TCCR4B, CS40); asm volatile( - " ldi r30, %[tccr4b] \n\t" - " ldi r24, %[value] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr4b] \n" + " ldi r24, %[value] \n" + " st z, r24 \n" : : [tccr4b] "M" (_SFR_MEM_ADDR(TCCR4B)), [value] "M" (_BV(CS42) | _BV(CS41) | _BV(CS40)) @@ -684,9 +641,9 @@ void init() //assembly optimized by 68 bytes ); //sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode asm volatile( - " ldi r30, %[tccr4d] \n\t" - " ldi r24, %[wgm40] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr4d] \n" + " ldi r24, %[wgm40] \n" + " st z, r24 \n" : : [tccr4d] "M" (_SFR_MEM_ADDR(TCCR4D)), [wgm40] "M" (_BV(WGM40)) @@ -694,9 +651,9 @@ void init() //assembly optimized by 68 bytes ); //sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A asm volatile( - " ldi r30, %[tccr4a] \n\t" - " ldi r24, %[pwm4a] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr4a] \n" + " ldi r24, %[pwm4a] \n" + " st z, r24 \n" : : [tccr4a] "M" (_SFR_MEM_ADDR(TCCR4A)), [pwm4a] "M" (_BV(PWM4A)) @@ -704,9 +661,9 @@ void init() //assembly optimized by 68 bytes ); //sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D asm volatile( - " ldi r30, %[tccr4c] \n\t" - " ldi r24, %[value] \n\t" - " st z, r24 \n\t" + " ldi r30, %[tccr4c] \n" + " ldi r24, %[value] \n" + " st z, r24 \n" : : [tccr4c] "M" (_SFR_MEM_ADDR(TCCR4C)), [value] "M" (_BV(PWM4D)) @@ -733,9 +690,9 @@ void init() //assembly optimized by 68 bytes //sbi(ADCSRA, ADPS1); //sbi(ADCSRA, ADPS0); asm volatile( - " ldi r30, %[adcsra] \n\t" - " ldi r24, %[value] \n\t" - " st z, r24 \n\t" + " ldi r30, %[adcsra] \n" + " ldi r24, %[value] \n" + " st z, r24 \n" : : [adcsra] "M" (_SFR_MEM_ADDR(ADCSRA)), [value] "M" (_BV(ADPS2) |_BV(ADPS1) | _BV(ADPS0)) @@ -746,9 +703,9 @@ void init() //assembly optimized by 68 bytes //sbi(ADCSRA, ADPS1); //cbi(ADCSRA, ADPS0); asm volatile( - " ldi r30, %[adcsra] \n\t" - " ldi r24, %[value] \n\t" - " st z, r24 \n\t" + " ldi r30, %[adcsra] \n" + " ldi r24, %[value] \n" + " st z, r24 \n" : : [adcsra] "M" (_SFR_MEM_ADDR(ADCSRA)), [value] "M" (_BV(ADPS2) | _BV(ADPS1)) @@ -774,14 +731,14 @@ void init() //assembly optimized by 68 bytes // enable a2d conversions //sbi(ADCSRA, ADEN); asm volatile( - " ori r24, %[aden] \n\t" - " st z, r24 \n\t" + " ori r24, %[aden] \n" + " st z, r24 \n" : : [aden] "M" (_BV(ADEN)) : "r24", "r30", "r31" ); #endif - + //(below not relevant for atmega32u4) // the bootloader connects pins 0 and 1 to the USART; disconnect them // here so they can be used as normal digital i/o; they will be // reconnected in Serial.begin() diff --git a/board-package-source/cores/arduboy/wiring_shift.c b/board-package-source/cores/arduboy/wiring_shift.c index 2b6f7a8..a9b3be5 100644 --- a/board-package-source/cores/arduboy/wiring_shift.c +++ b/board-package-source/cores/arduboy/wiring_shift.c @@ -42,10 +42,13 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) uint8_t i; for (i = 0; i < 8; i++) { - if (bitOrder == LSBFIRST) - digitalWrite(dataPin, !!(val & (1 << i))); - else - digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + if (bitOrder == LSBFIRST) { + digitalWrite(dataPin, val & 1); + val >>= 1; + } else { + digitalWrite(dataPin, (val & 128) != 0); + val <<= 1; + } digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW);