From 3c3bc0f52322e70b77a7c6bd4af475920c84b370 Mon Sep 17 00:00:00 2001 From: Makuna Date: Fri, 29 May 2015 13:30:15 -0700 Subject: [PATCH 1/2] Timer0 and Servo library support This exposes the Timer0 This provides a Servo library support compatible with Arduino Servo library but only supports the two timers the esp8266 has available --- cores/esp8266/Arduino.h | 18 +- cores/esp8266/core_esp8266_timer.c | 51 ++++- libraries/Servo/examples/Sweep/Sweep.ino | 39 ++++ libraries/Servo/keywords.txt | 24 +++ libraries/Servo/library.properties | 9 + libraries/Servo/src/Servo.h | 93 ++++++++ libraries/Servo/src/esp8266/Servo.cpp | 249 ++++++++++++++++++++++ libraries/Servo/src/esp8266/ServoTimers.h | 227 ++++++++++++++++++++ tools/sdk/include/ets_sys.h | 24 +++ 9 files changed, 727 insertions(+), 7 deletions(-) create mode 100644 libraries/Servo/examples/Sweep/Sweep.ino create mode 100644 libraries/Servo/keywords.txt create mode 100644 libraries/Servo/library.properties create mode 100644 libraries/Servo/src/Servo.h create mode 100644 libraries/Servo/src/esp8266/Servo.cpp create mode 100644 libraries/Servo/src/esp8266/ServoTimers.h diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 9d3f18ed9..6d8dc1eb5 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -99,13 +99,29 @@ void yield(void); #define timer1_enabled() ((T1C & (1 << TCTE)) != 0) #define timer1_interrupted() ((T1C & (1 << TCIS)) != 0) +typedef void(*timercallback)(void); + void timer1_isr_init(void); void timer1_enable(uint8_t divider, uint8_t int_type, uint8_t reload); void timer1_disable(void); -void timer1_attachInterrupt(void (*userFunc)(void)); +void timer1_attachInterrupt(timercallback userFunc); void timer1_detachInterrupt(void); void timer1_write(uint32_t ticks); //maximum ticks 8388607 +// timer0 is a special CPU timer that has very high resolution but with +// limited control. +// it uses CCOUNT (ESP.GetCycleCount()) as the non-resetable timer counter +// it does not support divide, type, or reload flags +// it is auto-disabled when the compare value matches CCOUNT +// it is auto-enabled when the compare value changes +#define timer0_interrupted() (ETS_INTR_PENDING() & (_BV(ETS_COMPARE0_INUM))) +#define timer0_read() ((__extension__({uint32_t count;__asm__ __volatile__("esync; rsr %0,ccompare0":"=a" (count));count;}))) +#define timer0_write(count) __asm__ __volatile__("wsr %0,ccompare0; esync"::"a" (count) : "memory") + +void timer0_isr_init(void); +void timer0_attachInterrupt(timercallback userFunc); +void timer0_detachInterrupt(void); + // undefine stdlib's abs if encountered #ifdef abs #undef abs diff --git a/cores/esp8266/core_esp8266_timer.c b/cores/esp8266/core_esp8266_timer.c index 048f6fa87..08b971c58 100644 --- a/cores/esp8266/core_esp8266_timer.c +++ b/cores/esp8266/core_esp8266_timer.c @@ -20,22 +20,33 @@ */ #include "wiring_private.h" #include "pins_arduino.h" +#ifdef __cplusplus +extern "C" { +#endif + #include "c_types.h" #include "ets_sys.h" -void (*timer1_user_cb)(void); +#ifdef __cplusplus +} +#endif + +/ ------------------------------------------------------------------ - +// timer 1 + +static volatile timercallback timer1_user_cb = NULL; void timer1_isr_handler(void *para){ - if((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable + if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable T1I = 0; - if(timer1_user_cb) timer1_user_cb(); + if (timer1_user_cb) timer1_user_cb(); } void timer1_isr_init(){ ETS_FRC_TIMER1_INTR_ATTACH(timer1_isr_handler, NULL); } -void timer1_attachInterrupt(void (*userFunc)(void)) { +void timer1_attachInterrupt(timercallback userFunc) { timer1_user_cb = userFunc; ETS_FRC1_INTR_ENABLE(); } @@ -52,11 +63,39 @@ void timer1_enable(uint8_t divider, uint8_t int_type, uint8_t reload){ } void timer1_write(uint32_t ticks){ - T1L = ((ticks) & 0x7FFFFF); - if((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable + T1L = ((ticks)& 0x7FFFFF); + if ((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable } void timer1_disable(){ T1C = 0; T1I = 0; } + +//------------------------------------------------------------------- +// timer 0 + +static volatile timercallback timer0_user_cb = NULL; + +void timer0_isr_handler(void* para){ + if (timer0_user_cb) { + timer0_user_cb(); + } +} + +void timer0_isr_init(){ + ETS_CCOMPARE0_INTR_ATTACH(timer0_isr_handler, NULL); +} + +void timer0_attachInterrupt(timercallback userFunc) { + timer0_user_cb = userFunc; + ETS_CCOMPARE0_ENABLE(); +} + +void timer0_detachInterrupt() { + timer0_user_cb = NULL; + ETS_CCOMPARE0_DISABLE(); +} + + + diff --git a/libraries/Servo/examples/Sweep/Sweep.ino b/libraries/Servo/examples/Sweep/Sweep.ino new file mode 100644 index 000000000..fe4e343ce --- /dev/null +++ b/libraries/Servo/examples/Sweep/Sweep.ino @@ -0,0 +1,39 @@ +/* Sweep + by BARRAGAN + This example code is in the public domain. + + modified 28 May 2015 + by Michael C. Miller + modified 8 Nov 2013 + by Scott Fitzgerald + + http://arduino.cc/en/Tutorial/Sweep +*/ + +#include + +Servo myservo; // create servo object to control a servo + // twelve servo objects can be created on most boards + + +void setup() +{ + myservo.attach(2); // attaches the servo on GIO2 to the servo object +} + +void loop() +{ + int pos; + + for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees + { // in steps of 1 degree + myservo.write(pos); // tell servo to go to position in variable 'pos' + delay(15); // waits 15ms for the servo to reach the position + } + for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees + { + myservo.write(pos); // tell servo to go to position in variable 'pos' + delay(15); // waits 15ms for the servo to reach the position + } +} + diff --git a/libraries/Servo/keywords.txt b/libraries/Servo/keywords.txt new file mode 100644 index 000000000..0a7ca1e3d --- /dev/null +++ b/libraries/Servo/keywords.txt @@ -0,0 +1,24 @@ +####################################### +# Syntax Coloring Map Servo +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Servo KEYWORD1 Servo + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +attach KEYWORD2 +detach KEYWORD2 +write KEYWORD2 +read KEYWORD2 +attached KEYWORD2 +writeMicroseconds KEYWORD2 +readMicroseconds KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/Servo/library.properties b/libraries/Servo/library.properties new file mode 100644 index 000000000..28b1eedf7 --- /dev/null +++ b/libraries/Servo/library.properties @@ -0,0 +1,9 @@ +name=Servo +version=1.0.2 +author=Michael C. Miller +maintainer=GitHub/esp8266/arduino +sentence=Allows Esp8266 boards to control a variety of servo motors. +paragraph=This library can control a great number of servos.
It makes careful use of timers: the library can control 12 servos using only 1 timer.
+category=Device Control +url=http://arduino.cc/en/Reference/Servo +architectures=esp8266 diff --git a/libraries/Servo/src/Servo.h b/libraries/Servo/src/Servo.h new file mode 100644 index 000000000..10cfd3283 --- /dev/null +++ b/libraries/Servo/src/Servo.h @@ -0,0 +1,93 @@ +/* + Servo.h - Interrupt driven Servo library for Esp8266 using timers + Copyright (c) 2015 Michael C. Miller. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +// A servo is activated by creating an instance of the Servo class passing +// the desired pin to the attach() method. +// The servos are pulsed in the background using the value most recently +// written using the write() method. +// +// This library uses time0 and timer1. +// Note that timer0 may be repurposed when the first servo is attached. +// +// Timers are seized as needed in groups of 12 servos - 24 servos use two +// timers, there are only two timers for the esp8266 so the support stops here +// The sequence used to sieze timers is defined in timers.h +// +// The methods are: +// +// Servo - Class for manipulating servo motors connected to Arduino pins. +// +// attach(pin ) - Attaches a servo motor to an i/o pin. +// attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds +// default min is 544, max is 2400 +// +// write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds) +// writeMicroseconds() - Sets the servo pulse width in microseconds +// read() - Gets the last written servo pulse width as an angle between 0 and 180. +// readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release) +// attached() - Returns true if there is a servo attached. +// detach() - Stops an attached servos from pulsing its i/o pin. + + +#ifndef Servo_h +#define Servo_h + +#include + +// the following are in us (microseconds) +// +#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo +#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo +#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached +#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds + +// NOTE: to maintain a strict refresh interval the user needs to not exceede 8 servos +#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer +#define MAX_SERVOS (ServoTimerSequence_COUNT * SERVOS_PER_TIMER) + +#if defined(ESP8266) + +#include "esp8266/ServoTimers.h" + +#else + +#error "This library only supports esp8266 boards." + +#endif + +class Servo +{ +public: + Servo(); + uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure + uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. + void detach(); + void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds + void writeMicroseconds(int value); // Write pulse width in microseconds + int read(); // returns current pulse width as an angle between 0 and 180 degrees + int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release) + bool attached(); // return true if this servo is attached, otherwise false +private: + uint8_t _servoIndex; // index into the channel data for this servo + uint16_t _minUs; + uint16_t _maxUs; +}; + +#endif diff --git a/libraries/Servo/src/esp8266/Servo.cpp b/libraries/Servo/src/esp8266/Servo.cpp new file mode 100644 index 000000000..bbc7bb26f --- /dev/null +++ b/libraries/Servo/src/esp8266/Servo.cpp @@ -0,0 +1,249 @@ +/* + Copyright (c) 2015 Michael C. Miller. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(ESP8266) + +#include +#include + + +#define INVALID_SERVO 255 // flag indicating an invalid servo index + +const uint32_t c_CycleCompensation = 4; // compensation us to trim adjust for digitalWrite delays + +struct ServoInfo { + uint8_t pin : 6; // a pin number from 0 to 63 + uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false +}; + +struct ServoState { + ServoInfo info; + volatile uint16_t usPulse; +}; + +#if !defined (SERVO_EXCLUDE_TIMER0) +ServoTimer0 s_servoTimer0; +#endif + +#if !defined (SERVO_EXCLUDE_TIMER1) +ServoTimer1 s_servoTimer1; +#endif + +static ServoState s_servos[MAX_SERVOS]; // static array of servo structures + +static uint8_t s_servoCount = 0; // the total number of attached s_servos + + +// inconvenience macros +#define SERVO_INDEX_TO_TIMER(servoIndex) ((ServoTimerSequence)(servoIndex / SERVOS_PER_TIMER)) // returns the timer controlling this servo +#define SERVO_INDEX(timerId, channel) ((timerId * SERVOS_PER_TIMER) + channel) // macro to access servo index by timer and channel + +//------------------------------------------------------------------------------ +// Interrupt handler template method that takes a class that implements +// a standard set of methods for the timer abstraction +//------------------------------------------------------------------------------ +template void Servo_Handler(T* timer) +{ + noInterrupts(); + + uint8_t servoIndex; + + // clear interrupt + timer->ResetInterrupt(); + + if (timer->isEndOfCycle()) { + timer->StartCycle(); + } + else { + servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel()); + if (servoIndex < s_servoCount && s_servos[servoIndex].info.isActive) { + // pulse this channel low if activated + digitalWrite(s_servos[servoIndex].info.pin, LOW); + } + timer->nextChannel(); + } + + servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel()); + + if (servoIndex < s_servoCount && timer->getCurrentChannel() < SERVOS_PER_TIMER) { + timer->SetPulseCompare(timer->usToTicks(s_servos[servoIndex].usPulse) - c_CycleCompensation); + + if (s_servos[servoIndex].info.isActive) { // check if activated + digitalWrite(s_servos[servoIndex].info.pin, HIGH); // its an active channel so pulse it high + } + } + else { + // finished all channels so wait for the refresh period to expire before starting over + // allow a few ticks to ensure the next match is not missed + uint32_t refreshCompare = timer->usToTicks(REFRESH_INTERVAL); + if ((timer->GetCycleCount() + c_CycleCompensation * 2) < refreshCompare) { + timer->SetCycleCompare(refreshCompare - c_CycleCompensation); + } + else { + // at least REFRESH_INTERVAL has elapsed + timer->SetCycleCompare(timer->GetCycleCount() + c_CycleCompensation * 2); + } + + timer->setEndOfCycle(); + } + + interrupts(); +} + +static void initISR(ServoTimerSequence timerId) +{ +#if !defined (SERVO_EXCLUDE_TIMER0) + if (timerId == ServoTimerSequence_Timer0) + s_servoTimer0.InitInterrupt([]() {Servo_Handler(&s_servoTimer0); }); +#endif +#if !defined (SERVO_EXCLUDE_TIMER1) + if (timerId == ServoTimerSequence_Timer1) + s_servoTimer1.InitInterrupt([]() {Servo_Handler(&s_servoTimer1); }); +#endif +} + +static void finISR(ServoTimerSequence timerId) +{ +#if !defined (SERVO_EXCLUDE_TIMER0) + if (timerId == ServoTimerSequence_Timer0) + s_servoTimer0.StopInterrupt(); +#endif +#if !defined (SERVO_EXCLUDE_TIMER1) + if (timerId == ServoTimerSequence_Timer1) + s_servoTimer1.StopInterrupt(); +#endif +} + +// returns true if any servo is active on this timer +static boolean isTimerActive(ServoTimerSequence timerId) +{ + for (uint8_t channel = 0; channel < SERVOS_PER_TIMER; channel++) { + if (s_servos[SERVO_INDEX(timerId, channel)].info.isActive) { + return true; + } + } + return false; +} + +//------------------------------------------------------------------- +// Servo class methods + +Servo::Servo() +{ + if (s_servoCount < MAX_SERVOS) { + // assign a servo index to this instance + _servoIndex = s_servoCount++; + // store default values + s_servos[_servoIndex].usPulse = DEFAULT_PULSE_WIDTH; + } + else { + _servoIndex = INVALID_SERVO; // too many servos + } +} + +uint8_t Servo::attach(int pin) +{ + return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); +} + +uint8_t Servo::attach(int pin, int minUs, int maxUs) +{ + ServoTimerSequence timerId; + + Serial.print("_servoIndex "); + Serial.println(_servoIndex); + + if (_servoIndex < MAX_SERVOS) { + pinMode(pin, OUTPUT); // set servo pin to output + digitalWrite(pin, LOW); + s_servos[_servoIndex].info.pin = pin; + + // keep the min and max within 200-3000 us, these are extreme + // ranges and should support extreme servos while maintaining + // reasonable ranges + _maxUs = max(250, min(3000, maxUs)); + _minUs = max(200, min(_maxUs, minUs)); + + // initialize the timerId if it has not already been initialized + timerId = SERVO_INDEX_TO_TIMER(_servoIndex); + if (!isTimerActive(timerId)) { + initISR(timerId); + } + s_servos[_servoIndex].info.isActive = true; // this must be set after the check for isTimerActive + } + return _servoIndex; +} + +void Servo::detach() +{ + ServoTimerSequence timerId; + + s_servos[_servoIndex].info.isActive = false; + timerId = SERVO_INDEX_TO_TIMER(_servoIndex); + if (!isTimerActive(timerId)) { + finISR(timerId); + } +} + +void Servo::write(int value) +{ + // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds) + if (value < MIN_PULSE_WIDTH) { + // assumed to be 0-180 degrees servo + value = max(0, min(180, value)); + value = map(value, 0, 180, _minUs, _maxUs); + } + writeMicroseconds(value); +} + +void Servo::writeMicroseconds(int value) +{ + // ensure channel is valid + if ((_servoIndex < MAX_SERVOS)) { + // ensure pulse width is valid + value = max(_minUs, min(_maxUs, value)); + + s_servos[_servoIndex].usPulse = value; + } +} + +int Servo::read() // return the value as degrees +{ + return map(readMicroseconds(), _minUs, _maxUs, 0, 180); +} + +int Servo::readMicroseconds() +{ + unsigned int pulsewidth; + if (_servoIndex != INVALID_SERVO) { + pulsewidth = s_servos[_servoIndex].usPulse; + } + else { + pulsewidth = 0; + } + + return pulsewidth; +} + +bool Servo::attached() +{ + return s_servos[_servoIndex].info.isActive; +} + +#endif + diff --git a/libraries/Servo/src/esp8266/ServoTimers.h b/libraries/Servo/src/esp8266/ServoTimers.h new file mode 100644 index 000000000..56ee18671 --- /dev/null +++ b/libraries/Servo/src/esp8266/ServoTimers.h @@ -0,0 +1,227 @@ +/* + Copyright (c) 2015 Michael C. Miller. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// +// Defines for timer abstractions used with Servo library +// +// ServoTimerSequence enumerates the sequence that the timers should be allocated +// ServoTimerSequence_COUNT indicates how many timers are available. +// +enum ServoTimerSequence { + +#if !defined (SERVO_EXCLUDE_TIMER0) + ServoTimerSequence_Timer0, +#endif + +#if !defined (SERVO_EXCLUDE_TIMER1) + ServoTimerSequence_Timer1, +#endif + + ServoTimerSequence_COUNT +}; + + +#if !defined (SERVO_EXCLUDE_TIMER0) + +struct ServoTimer0 +{ +public: + ServoTimer0() + { + setEndOfCycle(); + } + + + uint32_t usToTicks(uint32_t us) const + { + return (clockCyclesPerMicrosecond() * us); // converts microseconds to tick + } + uint32_t ticksToUs(uint32_t ticks) const + { + return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds + } + + void InitInterrupt(timercallback handler) + { + timer0_isr_init(); + timer0_attachInterrupt(handler); + } + + void ResetInterrupt() {}; // timer0 doesn't have a clear interrupt + + void StopInterrupt() + { + timer0_detachInterrupt(); + } + + void SetPulseCompare(uint32_t value) + { + timer0_write(ESP.getCycleCount() + value); + } + + void SetCycleCompare(uint32_t value) + { + timer0_write(_cycleStart + value); + } + + uint32_t GetCycleCount() const + { + return ESP.getCycleCount() - _cycleStart; + } + + + void StartCycle() + { + _cycleStart = ESP.getCycleCount(); + _currentChannel = 0; + } + + int8_t getCurrentChannel() const + { + return _currentChannel; + } + + void nextChannel() + { + _currentChannel++; + } + + void setEndOfCycle() + { + _currentChannel = -1; + } + + bool isEndOfCycle() const + { + return (_currentChannel == -1); + } + + ServoTimerSequence timerId() const + { + return ServoTimerSequence_Timer0; + } + +private: + volatile uint32_t _cycleStart; + volatile int8_t _currentChannel; +}; + +#endif + + +#if !defined (SERVO_EXCLUDE_TIMER1) + +struct ServoTimer1 +{ +public: + ServoTimer1() + { + setEndOfCycle(); + } + + + uint32_t usToTicks(uint32_t us) const + { + return (clockCyclesPerMicrosecond() / 16 * us); // converts microseconds to tick + } + uint32_t ticksToUs(uint32_t ticks) const + { + return (ticks / clockCyclesPerMicrosecond() * 16); // converts from ticks back to microseconds + } + + void InitInterrupt(timercallback handler) + { + timer1_isr_init(); + timer1_attachInterrupt(handler); + timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); + timer1_write(usToTicks(REFRESH_INTERVAL)); + } + + void ResetInterrupt() {}; // timer1 doesn't have a clear interrupt + + void StopInterrupt() + { + timer1_detachInterrupt(); + } + + void SetPulseCompare(uint32_t value) + { + _cycleTicks += value; + timer1_write(value); + } + + void SetCycleCompare(uint32_t value) + { + if (value <= _cycleTicks) + { + value = 1; + } + else + { + value -= _cycleTicks; + } + timer1_write(value); + } + + uint32_t GetCycleCount() const + { + return _cycleTicks; + } + + + void StartCycle() + { + _cycleTicks = 0; + _currentChannel = 0; + } + + int8_t getCurrentChannel() const + { + return _currentChannel; + } + + void nextChannel() + { + _currentChannel++; + } + + void setEndOfCycle() + { + _currentChannel = -1; + } + + bool isEndOfCycle() const + { + return (_currentChannel == -1); + } + + ServoTimerSequence timerId() const + { + return ServoTimerSequence_Timer1; + } + +private: + volatile uint32_t _cycleTicks; + volatile int8_t _currentChannel; +}; + +#endif + + + + diff --git a/tools/sdk/include/ets_sys.h b/tools/sdk/include/ets_sys.h index 389918be4..ad1a4c7be 100644 --- a/tools/sdk/include/ets_sys.h +++ b/tools/sdk/include/ets_sys.h @@ -43,6 +43,7 @@ typedef void (*int_handler_t)(void*); #define ETS_GPIO_INUM 4 #define ETS_UART_INUM 5 #define ETS_UART1_INUM 5 +#define ETS_CCOMPARE0_INUM 6 #define ETS_FRC_TIMER1_INUM 9 /* use edge*/ #define ETS_INTR_LOCK() \ @@ -51,6 +52,23 @@ typedef void (*int_handler_t)(void*); #define ETS_INTR_UNLOCK() \ ets_intr_unlock() +inline uint32_t ETS_INTR_ENABLED(void) +{ + uint32_t enabled; + __asm__ __volatile__("esync; rsr %0,intenable":"=a" (enabled)); + return enabled; +} + +inline uint32_t ETS_INTR_PENDING(void) +{ + uint32_t pending; + __asm__ __volatile__("esync; rsr %0,interrupt":"=a" (pending)); + return pending; +} + +#define ETS_CCOMPARE0_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_CCOMPARE0_INUM, (int_handler_t)(func), (void *)(arg)) + #define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \ ets_isr_attach(ETS_FRC_TIMER1_INUM, (int_handler_t)(func), (void *)(arg)) @@ -78,6 +96,12 @@ typedef void (*int_handler_t)(void*); #define ETS_UART_INTR_DISABLE() \ ETS_INTR_DISABLE(ETS_UART_INUM) +#define ETS_CCOMPARE0_ENABLE() \ + ETS_INTR_ENABLE(ETS_CCOMPARE0_INUM) + +#define ETS_CCOMPARE0_DISABLE() \ + ETS_INTR_DISABLE(ETS_CCOMPARE0_INUM) + #define ETS_FRC1_INTR_ENABLE() \ ETS_INTR_ENABLE(ETS_FRC_TIMER1_INUM) From 19554e563cc260b78474432ee2bd5210a587ddf2 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sat, 30 May 2015 15:10:56 +0300 Subject: [PATCH 2/2] add higher I2C freqs for 160MHz core clock --- cores/esp8266/core_esp8266_si2c.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cores/esp8266/core_esp8266_si2c.c b/cores/esp8266/core_esp8266_si2c.c index 1593bb859..d825c4445 100644 --- a/cores/esp8266/core_esp8266_si2c.c +++ b/cores/esp8266/core_esp8266_si2c.c @@ -47,14 +47,16 @@ void twi_setClock(unsigned int freq){ if(freq <= 100000) twi_dcount = 19;//about 100KHz else if(freq <= 200000) twi_dcount = 8;//about 200KHz else if(freq <= 300000) twi_dcount = 3;//about 300KHz - else if(freq <= 400000) twi_dcount = 1;//about 370KHz - else twi_dcount = 1;//about 450KHz + else if(freq <= 400000) twi_dcount = 1;//about 400KHz + else twi_dcount = 1;//about 400KHz #else if(freq <= 100000) twi_dcount = 32;//about 100KHz else if(freq <= 200000) twi_dcount = 14;//about 200KHz else if(freq <= 300000) twi_dcount = 8;//about 300KHz - else if(freq <= 400000) twi_dcount = 5;//about 370KHz - else twi_dcount = 2;//about 450KHz + else if(freq <= 400000) twi_dcount = 5;//about 400KHz + else if(freq <= 500000) twi_dcount = 3;//about 500KHz + else if(freq <= 600000) twi_dcount = 2;//about 600KHz + else twi_dcount = 1;//about 700KHz #endif }