1+ #if defined(ARDUINO_ARCH_ZEPHYR)
2+
3+ #include < zephyr/kernel.h>
4+ #include < zephyr/drivers/gpio.h>
5+ #include < zephyr/device.h>
6+ #include < zephyr/drivers/counter.h>
7+
8+ #include < Arduino.h>
9+ #include < Servo.h>
10+
11+
12+ typedef struct {
13+ uint8_t pin;
14+ uint32_t position_tick;
15+ uint32_t timer_index;
16+ uint32_t min;
17+ uint32_t max;
18+ } servoTimer_t;
19+
20+ class ServoTimerHandler {
21+
22+ inline static uint32_t timer_servo;
23+ inline static uint32_t servo_timing_period;
24+ bool timer_is_started;
25+
26+ inline static servoTimer_t * servos[MAX_ZEPHYR_SERVOS] = {nullptr };
27+ uint8_t servoCount;
28+
29+ public:
30+ ServoTimerHandler (){
31+ timer_is_started = false ;
32+ timer_servo = 0 ;
33+ servoCount = 0 ;
34+ }
35+
36+ int initTimer (){
37+ if (!timer_is_started){
38+ const struct device *const counter_dev = DEVICE_DT_GET (TIMER);
39+ counter_start (counter_dev);
40+ struct counter_top_cfg top_cfg;
41+ top_cfg.ticks = counter_us_to_ticks (counter_dev, servo_timer_base_us_tick);
42+ top_cfg.callback = this ->servo_timer_update ;
43+ top_cfg.user_data = &top_cfg;
44+ top_cfg.flags = 0 ;
45+
46+ int err = counter_set_top_value (counter_dev, &top_cfg);
47+ if (err){
48+ return 0 ;
49+ }
50+ else {
51+ timer_is_started = true ;
52+ return 1 ;
53+ }
54+ }
55+ return -1 ;
56+ }
57+
58+ static void servo_timer_update (const struct device *counter_dev, void *user_data){
59+ for (uint8_t i = 0 ; i < MAX_ZEPHYR_SERVOS; i++){
60+ if (servos[i]!=nullptr ){
61+ if (timer_servo>servos[i]->position_tick ){
62+ digitalWrite (servos[i]->pin , LOW);
63+ }
64+ else {
65+ digitalWrite (servos[i]->pin , HIGH);
66+ }
67+ }
68+ }
69+ if (timer_servo>servo_timer_end_tick){
70+ timer_servo = 0 ;
71+ }
72+ timer_servo++;
73+ }
74+
75+ int addServo (servoTimer_t * s){
76+ if (servoCount<MAX_ZEPHYR_SERVOS){
77+ for (uint8_t i = 0 ; i<MAX_ZEPHYR_SERVOS; i++){
78+ if (servos[i]!=nullptr && servos[i]->pin ==s->pin ){
79+ return i;
80+ }
81+ }
82+ for (uint8_t i = 0 ; i<MAX_ZEPHYR_SERVOS; i++){
83+ if (servos[i]==nullptr ){
84+ servos[i]=s;
85+ servoCount++;
86+ return i;
87+ }
88+ }
89+ }
90+ else {
91+ return -1 ;
92+ }
93+ return -2 ;
94+ }
95+
96+ int removeServo (int index){
97+ if (index<MAX_ZEPHYR_SERVOS){
98+ delete servos[index];
99+ servos[index]=nullptr ;
100+ servoCount--;
101+ return index;
102+ }
103+ else {
104+ return -1 ;
105+ }
106+ }
107+
108+ void writeMicroseconds (int index, int value){
109+ if (servos[index]!=nullptr ){
110+ servos[index]->position_tick = value/servo_timer_base_us_tick;
111+ }
112+ }
113+
114+ uint32_t getMin (int index){
115+ if (servos[index]!=nullptr ){
116+ return servos[index]->min ;
117+ }
118+ return MIN_PULSE_WIDTH;
119+ }
120+
121+ uint32_t getMax (int index){
122+ if (servos[index]!=nullptr ){
123+ return servos[index]->max ;
124+ }
125+ return MAX_PULSE_WIDTH;
126+ }
127+
128+ uint32_t readMicroseconds (int index){
129+ if (servos[index]!=nullptr ){
130+ return servos[index]->position_tick *servo_timer_base_us_tick;
131+ }
132+ return 0 ;
133+ }
134+ };
135+
136+ static ServoTimerHandler servo_handle;
137+
138+
139+ Servo::Servo (){
140+ servo_handle.initTimer ();
141+ servoIndex = 255 ;
142+ }
143+
144+ uint8_t Servo::attach (int pin){
145+ return this ->attach (pin, MIN_PULSE_WIDTH , MAX_PULSE_WIDTH );
146+ }
147+
148+ uint8_t Servo::attach (int pin, int min, int max){
149+ pinMode (pin, OUTPUT);
150+ servoTimer_t * tmp_servo = new servoTimer_t ();
151+ tmp_servo->pin = pin;
152+ tmp_servo->min = min;
153+ tmp_servo->max = max;
154+ servoIndex = servo_handle.addServo (tmp_servo);
155+ this ->min = servo_handle.getMin (servoIndex)/4 ;
156+ this ->max = servo_handle.getMax (servoIndex)/4 ;
157+ return 0 ;
158+ }
159+
160+
161+ void Servo::detach (){
162+ servo_handle.removeServo (servoIndex);
163+ servoIndex = 255 ;
164+ }
165+
166+ void Servo::write (int value){
167+ servo_handle.writeMicroseconds (servoIndex, map (value, 0 , 180 , servo_handle.getMin (servoIndex), servo_handle.getMax (servoIndex)));
168+ }
169+
170+ void Servo::writeMicroseconds (int value){
171+ servo_handle.writeMicroseconds (servoIndex, value);
172+ }
173+
174+ int Servo::read (){
175+ return map (servo_handle.readMicroseconds (servoIndex), servo_handle.getMin (servoIndex), servo_handle.getMax (servoIndex), 0 , 180 );
176+ }
177+
178+ int Servo::readMicroseconds (){
179+ return servo_handle.readMicroseconds (servoIndex);
180+ }
181+
182+ bool Servo::attached (){
183+ if (servoIndex==255 ){
184+ return false ;
185+ }
186+ else {
187+ return true ;
188+ }
189+ }
190+
191+ #endif
0 commit comments