1
+ /*
2
+ Copyright (c) 2016 Arduino. All right reserved.
3
+
4
+ This library is free software; you can redistribute it and/or
5
+ modify it under the terms of the GNU Lesser General Public
6
+ License as published by the Free Software Foundation; either
7
+ version 2.1 of the License, or (at your option) any later version.
8
+
9
+ This library is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ Lesser General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public
15
+ License along with this library; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
+ */
18
+
19
+ #if defined(ARDUINO_ARCH_NRF52)
20
+
21
+ #include < Arduino.h>
22
+ #include < Servo.h>
23
+
24
+
25
+ static servo_t servos[MAX_SERVOS]; // static array of servo structures
26
+
27
+ uint8_t ServoCount = 0 ; // the total number of attached servos
28
+
29
+
30
+
31
+ uint32_t group_pins[3 ][NRF_PWM_CHANNEL_COUNT]={{NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}, {NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}, {NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}};
32
+ static uint16_t seq_values[3 ][NRF_PWM_CHANNEL_COUNT]={{0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }};
33
+
34
+ Servo::Servo ()
35
+ {
36
+ if (ServoCount < MAX_SERVOS) {
37
+ this ->servoIndex = ServoCount++; // assign a servo index to this instance
38
+ } else {
39
+ this ->servoIndex = INVALID_SERVO; // too many servos
40
+ }
41
+
42
+ }
43
+
44
+ uint8_t Servo::attach (int pin)
45
+ {
46
+
47
+ return this ->attach (pin, 0 , 2500 );
48
+ }
49
+
50
+
51
+ uint8_t Servo::attach (int pin, int min, int max)
52
+ {
53
+ int servo_min, servo_max;
54
+ if (this ->servoIndex < MAX_SERVOS) {
55
+ pinMode (pin, OUTPUT); // set servo pin to output
56
+ servos[this ->servoIndex ].Pin .nbr = pin;
57
+
58
+ if (min < servo_min) min = servo_min;
59
+ if (max > servo_max) max = servo_max;
60
+ this ->min = min;
61
+ this ->max = max;
62
+
63
+ servos[this ->servoIndex ].Pin .isActive = true ;
64
+
65
+ }
66
+ return this ->servoIndex ;
67
+ }
68
+
69
+ void Servo::detach ()
70
+ {
71
+ servos[this ->servoIndex ].Pin .isActive = false ;
72
+ }
73
+
74
+
75
+ void Servo::write (int value)
76
+ {
77
+ if (value < 0 )
78
+ value = 0 ;
79
+ else if (value > 180 )
80
+ value = 180 ;
81
+ value = map (value, 0 , 180 , MIN_PULSE, MAX_PULSE);
82
+
83
+ writeMicroseconds (value);
84
+ }
85
+
86
+
87
+ void Servo::writeMicroseconds (int value)
88
+ {
89
+ uint8_t channel, instance;
90
+ uint8_t pin = servos[this ->servoIndex ].Pin .nbr ;
91
+ // instance of pwm module is MSB - look at VWariant.h
92
+ instance=(g_APinDescription[pin].ulPWMChannel & 0xF0 )/16 ;
93
+ // index of pwm channel is LSB - look at VWariant.h
94
+ channel=g_APinDescription[pin].ulPWMChannel & 0x0F ;
95
+ group_pins[instance][channel]=g_APinDescription[pin].ulPin ;
96
+ NRF_PWM_Type * PWMInstance = instance == 0 ? NRF_PWM0 : (instance == 1 ? NRF_PWM1 : NRF_PWM2);
97
+ // configure pwm instance and enable it
98
+ seq_values[instance][channel]= value | 0x8000 ;
99
+ nrf_pwm_sequence_t const seq={
100
+ seq_values[instance],
101
+ NRF_PWM_VALUES_LENGTH (seq_values),
102
+ 0 ,
103
+ 0
104
+ };
105
+ nrf_pwm_pins_set (PWMInstance, group_pins[instance]);
106
+ nrf_pwm_enable (PWMInstance);
107
+ nrf_pwm_configure (PWMInstance, NRF_PWM_CLK_125kHz, NRF_PWM_MODE_UP, 2500 ); // 20ms - 50Hz
108
+ nrf_pwm_decoder_set (PWMInstance, NRF_PWM_LOAD_INDIVIDUAL, NRF_PWM_STEP_AUTO);
109
+ nrf_pwm_sequence_set (PWMInstance, 0 , &seq);
110
+ nrf_pwm_loop_set (PWMInstance, 0UL );
111
+ nrf_pwm_task_trigger (PWMInstance, NRF_PWM_TASK_SEQSTART0);
112
+ }
113
+
114
+ int Servo::read () // return the value as degrees
115
+ {
116
+ return map (readMicroseconds (), MIN_PULSE, MAX_PULSE, 0 , 180 );
117
+ }
118
+
119
+ int Servo::readMicroseconds ()
120
+ {
121
+ uint8_t channel, instance;
122
+ uint8_t pin=servos[this ->servoIndex ].Pin .nbr ;
123
+ instance=(g_APinDescription[pin].ulPWMChannel & 0xF0 )/16 ;
124
+ channel=g_APinDescription[pin].ulPWMChannel & 0x0F ;
125
+ // remove the 16th bit we added before
126
+ return seq_values[instance][channel] & 0x7FFF ;
127
+ }
128
+
129
+ bool Servo::attached ()
130
+ {
131
+ return servos[this ->servoIndex ].Pin .isActive ;
132
+ }
133
+
134
+ #endif // ARDUINO_ARCH_NRF52
0 commit comments