diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 829514d..737d537 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -75,6 +75,10 @@ jobs: platforms: | - name: arduino:esp32 artifact-name-suffix: arduino-esp32-nano_nora + - fqbn: arduino:zephyr:unoq + platforms: | + - name: arduino:zephyr + artifact-name-suffix: arduino-zephyr-unoq steps: - name: Checkout repository diff --git a/library.properties b/library.properties index 4d17a02..59b0cc8 100644 --- a/library.properties +++ b/library.properties @@ -6,4 +6,4 @@ sentence=Allows Arduino 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.
On the Arduino Due you can control up to 60 servos. category=Device Control url=https://www.arduino.cc/reference/en/libraries/servo/ -architectures=avr,megaavr,sam,samd,nrf52,stm32f4,mbed,mbed_nano,mbed_portenta,mbed_rp2040,renesas,renesas_portenta,renesas_uno +architectures=avr,megaavr,sam,samd,nrf52,stm32f4,mbed,mbed_nano,mbed_portenta,mbed_rp2040,renesas,renesas_portenta,renesas_uno,zephyr diff --git a/src/Servo.h b/src/Servo.h index ed6f56a..20abb2c 100644 --- a/src/Servo.h +++ b/src/Servo.h @@ -79,8 +79,10 @@ #include "xmc/ServoTimers.h" #elif defined(ARDUINO_ARCH_ESP32) #include "esp32/ServoTimers.h" +#elif defined(ARDUINO_ARCH_ZEPHYR) +#include "zephyr/ServoTimers.h" #else -#error "This library only supports boards with an AVR, SAM, SAMD, NRF52, STM32F4, Renesas, XMC or ESP32 processor." +#error "This library only supports boards with an AVR, SAM, SAMD, NRF52, STM32F4, Renesas, XMC, ESP32 or Zephyr core." #endif #define Servo_VERSION 2 // software version of this library diff --git a/src/zephyr/Servo.cpp b/src/zephyr/Servo.cpp new file mode 100644 index 0000000..1e65596 --- /dev/null +++ b/src/zephyr/Servo.cpp @@ -0,0 +1,191 @@ +#if defined(ARDUINO_ARCH_ZEPHYR) + +#include +#include +#include +#include + +#include +#include + + +typedef struct { + uint8_t pin; + uint32_t position_tick; + uint32_t timer_index; + uint32_t min; + uint32_t max; +} servoTimer_t; + +class ServoTimerHandler{ + + inline static uint32_t timer_servo; + inline static uint32_t servo_timing_period; + bool timer_is_started; + + inline static servoTimer_t * servos[MAX_ZEPHYR_SERVOS] = {nullptr}; + uint8_t servoCount; + + public: + ServoTimerHandler(){ + timer_is_started = false; + timer_servo = 0; + servoCount = 0; + } + + int initTimer(){ + if (!timer_is_started){ + const struct device *const counter_dev = DEVICE_DT_GET(TIMER); + counter_start(counter_dev); + struct counter_top_cfg top_cfg; + top_cfg.ticks = counter_us_to_ticks(counter_dev, servo_timer_base_us_tick); + top_cfg.callback = this->servo_timer_update; + top_cfg.user_data = &top_cfg; + top_cfg.flags = 0; + + int err = counter_set_top_value(counter_dev, &top_cfg); + if (err){ + return 0; + } + else{ + timer_is_started = true; + return 1; + } + } + return -1; + } + + static void servo_timer_update(const struct device *counter_dev, void *user_data){ + for (uint8_t i = 0; i < MAX_ZEPHYR_SERVOS; i++){ + if (servos[i]!=nullptr){ + if (timer_servo>servos[i]->position_tick){ + digitalWrite(servos[i]->pin, LOW); + } + else{ + digitalWrite(servos[i]->pin, HIGH); + } + } + } + if (timer_servo>servo_timer_end_tick){ + timer_servo = 0; + } + timer_servo++; + } + + int addServo(servoTimer_t * s){ + if (servoCountpin==s->pin){ + return i; + } + } + for (uint8_t i = 0; iposition_tick = value/servo_timer_base_us_tick; + } + } + + uint32_t getMin(int index){ + if (servos[index]!=nullptr){ + return servos[index]->min; + } + return MIN_PULSE_WIDTH; + } + + uint32_t getMax(int index){ + if (servos[index]!=nullptr){ + return servos[index]->max; + } + return MAX_PULSE_WIDTH; + } + + uint32_t readMicroseconds(int index){ + if (servos[index]!=nullptr){ + return servos[index]->position_tick*servo_timer_base_us_tick; + } + return 0; + } +}; + +static ServoTimerHandler servo_handle; + + +Servo::Servo(){ + servo_handle.initTimer(); + servoIndex = 255; +} + +uint8_t Servo::attach(int pin){ + return this->attach(pin, MIN_PULSE_WIDTH , MAX_PULSE_WIDTH ); +} + +uint8_t Servo::attach(int pin, int min, int max){ + pinMode(pin, OUTPUT); + servoTimer_t * tmp_servo = new servoTimer_t(); + tmp_servo->pin = pin; + tmp_servo->min = min; + tmp_servo->max = max; + servoIndex = servo_handle.addServo(tmp_servo); + this->min = servo_handle.getMin(servoIndex)/4; + this->max = servo_handle.getMax(servoIndex)/4; + return 0; +} + + +void Servo::detach(){ + servo_handle.removeServo(servoIndex); + servoIndex = 255; +} + +void Servo::write(int value){ + servo_handle.writeMicroseconds(servoIndex, map(value, 0, 180, servo_handle.getMin(servoIndex), servo_handle.getMax(servoIndex))); +} + +void Servo::writeMicroseconds(int value){ + servo_handle.writeMicroseconds(servoIndex, value); +} + +int Servo::read(){ + return map(servo_handle.readMicroseconds(servoIndex), servo_handle.getMin(servoIndex), servo_handle.getMax(servoIndex), 0, 180); +} + +int Servo::readMicroseconds(){ + return servo_handle.readMicroseconds(servoIndex); +} + +bool Servo::attached(){ + if (servoIndex==255){ + return false; + } + else{ + return true; + } +} + +#endif \ No newline at end of file diff --git a/src/zephyr/ServoTimers.h b/src/zephyr/ServoTimers.h new file mode 100644 index 0000000..1fc6e19 --- /dev/null +++ b/src/zephyr/ServoTimers.h @@ -0,0 +1,6 @@ +#define MAX_ZEPHYR_SERVOS 16 + +#define TIMER DT_NODELABEL(counter_servo) + +const uint32_t servo_timer_base_us_tick = 4; +const uint32_t servo_timer_end_tick = 20000/servo_timer_base_us_tick;