From 2d7a1e71068fd4798a4cb6adb1ab7cc85d0625d9 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Mon, 9 Jun 2014 13:55:47 -0700 Subject: [PATCH 1/6] Begin non-AVR porting --- CShiftPWM.cpp | 134 +++++++++++++++++++++--------------- ShiftPWM.h | 22 ++++++ pins_arduino_compile_time.h | 23 +++++++ 3 files changed, 123 insertions(+), 56 deletions(-) diff --git a/CShiftPWM.cpp b/CShiftPWM.cpp index 726b2bc..cde0c71 100644 --- a/CShiftPWM.cpp +++ b/CShiftPWM.cpp @@ -304,18 +304,23 @@ void CShiftPWM::Start(int ledFrequency, unsigned char maxBrightness){ } if(LoadNotTooHigh() ){ - if(m_timer==1){ + switch (m_timer) { + #if defined(__AVR__) && defined(OCR1A) + case 1: InitTimer1(); - } - #if defined(USBCON) - else if(m_timer==3){ + break; + #endif + #if defined(__AVR__) && defined(OCR2A) + case 2: + InitTimer2(); + break; + #endif + #if defined(__AVR__) && defined(OCR3A) + case 3: InitTimer3(); - } - #else - else if(m_timer==2){ - InitTimer2(); - } + break; #endif + } } else{ Serial.println(F("Interrupts are disabled because load is too high.")); @@ -323,6 +328,7 @@ void CShiftPWM::Start(int ledFrequency, unsigned char maxBrightness){ } } +#if defined(__AVR__) && defined(OCR1A) void CShiftPWM::InitTimer1(void){ /* Configure timer1 in CTC mode: clear the timer on compare match * See the Atmega328 Datasheet 15.9.2 for an explanation on CTC mode. @@ -351,8 +357,9 @@ void CShiftPWM::InitTimer1(void){ /* Finally enable the timer interrupt, see datasheet 15.11.8) */ bitSet(TIMSK1,OCIE1A); } +#endif -#if defined(OCR2A) +#if defined(__AVR__) && defined(OCR2A) void CShiftPWM::InitTimer2(void){ /* Configure timer2 in CTC mode: clear the timer on compare match * See the Atmega328 Datasheet 15.9.2 for an explanation on CTC mode. @@ -402,7 +409,7 @@ void CShiftPWM::InitTimer2(void){ } #endif -#if defined(OCR3A) +#if defined(__AVR__) && defined(OCR3A) // Arduino Leonardo or Micro void CShiftPWM::InitTimer3(void){ /* @@ -446,8 +453,9 @@ void CShiftPWM::PrintInterruptLoad(void){ unsigned long start1,end1,time1,start2,end2,time2,k; double load, cycles_per_int, interrupt_frequency; - - if(m_timer==1){ + switch (m_timer) { + #if defined(__AVR__) && defined(OCR1A) + case 1: if(TIMSK1 & (1<counter ); } bitSet(*clockPort, clockBit); +#else + digitalWriteFast(clockBit, LOW); + if(ShiftPWM_invertOutputs){ + digitalWriteFast(dataBit, *(ledPtr)<=counter ); + } + else{ + digitalWriteFast(dataBit, *(ledPtr)>counter ); + } + digitalWriteFast(*clockPort, HIGH); +#endif } static inline void ShiftPWM_handleInterrupt(void){ @@ -123,7 +134,12 @@ static inline void ShiftPWM_handleInterrupt(void){ unsigned char * ledPtr=&ShiftPWM.m_PWMValues[ShiftPWM.m_amountOfOutputs]; // Write shift register latch clock low + #ifndef SHIFTPWM_USE_DIGITALWRITEFAST bitClear(*latchPort, latchBit); + #else + digitalWriteFast(latchBit, LOW); + #endif + unsigned char counter = ShiftPWM.m_counter; #ifndef SHIFTPWM_NOSPI @@ -169,7 +185,11 @@ static inline void ShiftPWM_handleInterrupt(void){ #endif // Write shift register latch clock high + #ifndef SHIFTPWM_USE_DIGITALWRITEFAST bitSet(*latchPort, latchBit); + #else + digitalWriteFast(latchBit, HIGH); + #endif if(ShiftPWM.m_counter Date: Mon, 9 Jun 2014 15:25:53 -0700 Subject: [PATCH 2/6] Finish porting to Teensy 3.1 --- CShiftPWM.cpp | 35 ++++++++++++++++++++++++++++++++++- ShiftPWM.h | 6 +++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/CShiftPWM.cpp b/CShiftPWM.cpp index cde0c71..ef1e2d8 100644 --- a/CShiftPWM.cpp +++ b/CShiftPWM.cpp @@ -240,7 +240,13 @@ bool CShiftPWM::LoadNotTooHigh(void){ // This is with inverted outputs, which is worst case. Without inverting, it would be 42 per register. float interruptDuration; if(m_noSPI){ +#if defined(__AVR__) interruptDuration = 96+108*(float) m_amountOfRegisters; +#else + // TODO: perhaps this is too pessimistic? Best to err on the + // side of caution to avoid overcommitting the CPU... + interruptDuration = 96+193*(float) m_amountOfRegisters; +#endif } else{ interruptDuration = 97+43* (float) m_amountOfRegisters; @@ -320,6 +326,11 @@ void CShiftPWM::Start(int ledFrequency, unsigned char maxBrightness){ InitTimer3(); break; #endif + #if defined(__arm__) && defined(CORE_TEENSY) + default: + InitTimer1(); + break; + #endif } } else{ @@ -359,6 +370,17 @@ void CShiftPWM::InitTimer1(void){ } #endif +#if defined(__arm__) && defined(CORE_TEENSY) +static IntervalTimer itimer; +extern void ShiftPWM_handleInterrupt(void); + +void CShiftPWM::InitTimer1(void){ + itimer.begin(ShiftPWM_handleInterrupt, + 1000000.0 / (m_ledFrequency * (m_maxBrightness+1))); +} +#endif + + #if defined(__AVR__) && defined(OCR2A) void CShiftPWM::InitTimer2(void){ /* Configure timer2 in CTC mode: clear the timer on compare match @@ -478,7 +500,7 @@ void CShiftPWM::PrintInterruptLoad(void){ } break; #endif - #if defined(__AVR__) && defined(OCR2A) + #if defined(__AVR__) && defined(OCR3A) case 3: if(TIMSK3 & (1<counter ); } - digitalWriteFast(*clockPort, HIGH); + digitalWriteFast(clockBit, HIGH); #endif } +#if defined(__AVR__) static inline void ShiftPWM_handleInterrupt(void){ +#else +void ShiftPWM_handleInterrupt(void){ +#endif sei(); //enable interrupt nesting to prevent disturbing other interrupt functions (servo's for example). // Look up which bit of which output register corresponds to the pin. From a472d1cc36b6829c8e9c223648bbdd603df3dbfb Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Tue, 19 Jan 2016 09:22:04 -0800 Subject: [PATCH 3/6] Support Teensy LC --- pins_arduino_compile_time.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pins_arduino_compile_time.h b/pins_arduino_compile_time.h index 8035867..b6df3d2 100644 --- a/pins_arduino_compile_time.h +++ b/pins_arduino_compile_time.h @@ -305,10 +305,10 @@ const uint8_t digital_pin_to_bit_PGM_ct[] = { 2, 3, 4, 5, 6, 7 }; -#elif defined(__MK20DX128__) || defined(__MK20DX256__) -// for Teensy 3.x +#elif defined(__arm__) && defined(CORE_TEENSY) +// for Teensy 3.x and Teensy LC #ifndef SHIFTPWM_NOSPI -#error "On Teensy 3.x, you must define SHIFTPWM_NOSPI, ShiftPWM_dataPin, ShiftPWM_clockPin" +#error "On Teensy 3.x & LC, you must define SHIFTPWM_NOSPI, ShiftPWM_dataPin, ShiftPWM_clockPin" #endif #define SHIFTPWM_USE_DIGITALWRITEFAST volatile uint8_t * const port_to_output_PGM_ct[] = { From bf9f68e0b0823d1563c1982305102ceecf4ac26c Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sat, 24 Dec 2016 10:35:34 -0800 Subject: [PATCH 4/6] Fix compiler warnings --- CShiftPWM.cpp | 6 +++--- ShiftPWM.h | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CShiftPWM.cpp b/CShiftPWM.cpp index ef1e2d8..56940eb 100644 --- a/CShiftPWM.cpp +++ b/CShiftPWM.cpp @@ -33,7 +33,7 @@ CShiftPWM::CShiftPWM(int timerInUse, bool noSPI, int latchPin, int dataPin, int m_counter = 0; m_pinGrouping = 1; // Default = RGBRGBRGB... PinGrouping = 3 means: RRRGGGBBBRRRGGGBBB... - unsigned char * m_PWMValues=0; + m_PWMValues=0; } CShiftPWM::~CShiftPWM() { @@ -129,7 +129,7 @@ void CShiftPWM::SetAllRGB(unsigned char r,unsigned char g,unsigned char b){ } void CShiftPWM::SetHSV(int led, unsigned int hue, unsigned int sat, unsigned int val, int offset){ - unsigned char r,g,b; + unsigned char r=0,g=0,b=0; unsigned int H_accent = hue/60; unsigned int bottom = ((255 - sat) * val)>>8; unsigned int top = val; @@ -195,7 +195,7 @@ void CShiftPWM::OneByOneFast(void){ void CShiftPWM::OneByOne_core(int delaytime){ int pin,brightness; SetAll(0); - for(int pin=0;pin Date: Wed, 15 Mar 2017 04:44:13 -0700 Subject: [PATCH 5/6] Bitbang delays to pmeet HC595 timing with faster Teensy 3.x --- ShiftPWM.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/ShiftPWM.h b/ShiftPWM.h index 04136da..30563ee 100644 --- a/ShiftPWM.h +++ b/ShiftPWM.h @@ -97,13 +97,55 @@ static inline void pwm_output_one_pin(volatile uint8_t * const clockPort, volati bitSet(*clockPort, clockBit); #else digitalWriteFast(clockBit, LOW); +#if F_CPU >= 120000000 + asm("nop"); +#endif +#if F_CPU >= 180000000 + asm("nop"); +#endif if(ShiftPWM_invertOutputs){ digitalWriteFast(dataBit, *(ledPtr)<=counter ); } else{ digitalWriteFast(dataBit, *(ledPtr)>counter ); } +#if F_CPU >= 96000000 + asm("nop"); +#endif +#if F_CPU >= 144000000 + asm("nop"); +#endif +#if F_CPU >= 192000000 + asm("nop"); +#endif digitalWriteFast(clockBit, HIGH); +#if F_CPU >= 48000000 + asm("nop"); +#endif +#if F_CPU >= 72000000 + asm("nop"); +#endif +#if F_CPU >= 96000000 + asm("nop"); +#endif +#if F_CPU >= 120000000 + asm("nop"); +#endif +#if F_CPU >= 144000000 + asm("nop"); +#endif +#if F_CPU >= 168000000 + asm("nop"); +#endif +#if F_CPU >= 180000000 + asm("nop"); +#endif +#if F_CPU >= 192000000 + asm("nop"); +#endif +#if F_CPU >= 216000000 + asm("nop"); +#endif #endif } From 4c25bfda72ac3cb99fc20ae7cb8c35aa8926e363 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 25 Apr 2024 11:52:18 -0700 Subject: [PATCH 6/6] Fix compile error with C++17 --- CShiftPWM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CShiftPWM.cpp b/CShiftPWM.cpp index 56940eb..a980107 100644 --- a/CShiftPWM.cpp +++ b/CShiftPWM.cpp @@ -37,7 +37,7 @@ CShiftPWM::CShiftPWM(int timerInUse, bool noSPI, int latchPin, int dataPin, int } CShiftPWM::~CShiftPWM() { - if(m_PWMValues>0){ + if(m_PWMValues){ free( m_PWMValues ); } }