Skip to content

Adds a preliminary support for zephyr boards #143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode/settings.json
4 changes: 3 additions & 1 deletion src/Servo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
191 changes: 191 additions & 0 deletions src/zephyr/Servo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#if defined(ARDUINO_ARCH_ZEPHYR)

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/device.h>
#include <zephyr/drivers/counter.h>

#include <Arduino.h>
#include <Servo.h>


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 (servoCount<MAX_ZEPHYR_SERVOS){
for (uint8_t i = 0; i<MAX_ZEPHYR_SERVOS; i++){
if (servos[i]!=nullptr && servos[i]->pin==s->pin){
return i;
}
}
for (uint8_t i = 0; i<MAX_ZEPHYR_SERVOS; i++){
if (servos[i]==nullptr){
servos[i]=s;
servoCount++;
return i;
}
}
}
else{
return -1;
}
return -2;
}

int removeServo(int index){
if (index<MAX_ZEPHYR_SERVOS){
delete servos[index];
servos[index]=nullptr;
servoCount--;
return index;
}
else{
return -1;
}
}

void writeMicroseconds(int index, int value){
if (servos[index]!=nullptr){
servos[index]->position_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
6 changes: 6 additions & 0 deletions src/zephyr/ServoTimers.h
Original file line number Diff line number Diff line change
@@ -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;