Skip to content

Commit ebff032

Browse files
authored
Merge pull request #25 from sparkfun/pulseIn
Pulse in
2 parents e1bdb84 + b02e443 commit ebff032

File tree

2 files changed

+153
-81
lines changed

2 files changed

+153
-81
lines changed

cores/arduino/ard_sup/ap3_gpio.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ SOFTWARE.
2525
#include "Arduino.h"
2626

2727
// User Config
28-
#define AP3_GPIO_MAX_EXT_INT_HANDLERS AP3_GPIO_MAX_PADS
28+
#define AP3_GPIO_MAX_EXT_INT_HANDLERS AP3_GPIO_MAX_PADS
2929
// End User Config
3030

3131
//GPIO FUNCTIONS
@@ -34,39 +34,41 @@ extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_WITH_READ_12;
3434
extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OPEN_DRAIN_WITH_READ_12;
3535
extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLDOWN;
3636

37-
#define INPUT (g_AM_HAL_GPIO_INPUT)
38-
#define OUTPUT (g_AM_HAL_GPIO_OUTPUT_WITH_READ_12)
39-
#define OPEN_DRAIN (g_AM_HAL_GPIO_OPEN_DRAIN_WITH_READ_12)
40-
#define TRISTATE (g_AM_HAL_GPIO_TRISTATE)
41-
#define INPUT_PULLUP (g_AM_HAL_GPIO_INPUT_PULLUP)
42-
#define INPUT_PULLDOWN (g_AM_HAL_GPIO_INPUT_PULLDOWN)
37+
#define INPUT (g_AM_HAL_GPIO_INPUT)
38+
#define OUTPUT (g_AM_HAL_GPIO_OUTPUT_WITH_READ_12)
39+
#define OPEN_DRAIN (g_AM_HAL_GPIO_OPEN_DRAIN_WITH_READ_12)
40+
#define TRISTATE (g_AM_HAL_GPIO_TRISTATE)
41+
#define INPUT_PULLUP (g_AM_HAL_GPIO_INPUT_PULLUP)
42+
#define INPUT_PULLDOWN (g_AM_HAL_GPIO_INPUT_PULLDOWN)
4343

44-
#define AP3_GPIO_MAX_PADS (50)
45-
#define AP3_GPIO_IS_VALID(pad) ((pad >= 0) && (pad < AP3_GPIO_MAX_PADS))
44+
#define AP3_GPIO_MAX_PADS (50)
45+
#define AP3_GPIO_IS_VALID(pad) ((pad >= 0) && (pad < AP3_GPIO_MAX_PADS))
4646

47-
extern ap3_gpio_pad_t ap3_gpio_pin2pad(ap3_gpio_pin_t pin);
48-
#define AP3_GPIO_PAD_UNUSED (-1)
47+
extern ap3_gpio_pad_t ap3_gpio_pin2pad(ap3_gpio_pin_t pin);
48+
#define AP3_GPIO_PAD_UNUSED (-1)
4949

5050
#define AP3_GPIO_DEFAULT_PINCFG AP3_GPIO_PINCFG_NULL
5151

5252
// apollo3 pad capabilities
53-
inline bool ap3_gpio_is_valid(ap3_gpio_pad_t pad){ return AP3_GPIO_IS_VALID(pad); }
54-
inline bool ap3_gpio_has_gpio(ap3_gpio_pad_t pad){ return AP3_GPIO_IS_VALID(pad); }
53+
inline bool ap3_gpio_is_valid(ap3_gpio_pad_t pad) { return AP3_GPIO_IS_VALID(pad); }
54+
inline bool ap3_gpio_has_gpio(ap3_gpio_pad_t pad) { return AP3_GPIO_IS_VALID(pad); }
5555

5656
// Interrupt enable/disable function
57-
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir );
57+
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir);
5858

5959
void padMode(uint8_t pad, am_hal_gpio_pincfg_t mode);
60-
void padMode(uint8_t pad, am_hal_gpio_pincfg_t mode, ap3_err_t* retval);
60+
void padMode(uint8_t pad, am_hal_gpio_pincfg_t mode, ap3_err_t *retval);
6161

6262
void pinMode(uint8_t pin, am_hal_gpio_pincfg_t mode);
63-
void pinMode(uint8_t pin, am_hal_gpio_pincfg_t mode, ap3_err_t* retval);
63+
void pinMode(uint8_t pin, am_hal_gpio_pincfg_t mode, ap3_err_t *retval);
6464
void digitalWrite(uint8_t pin, uint8_t val);
6565
int digitalRead(uint8_t pin);
6666

6767
void attachInterrupt(uint8_t pin, voidFuncPtr callback, int mode);
68-
void attachInterruptArg(uint8_t pin, voidFuncPtrArgs callbackArgs, void * arg, int mode);
68+
void attachInterruptArg(uint8_t pin, voidFuncPtrArgs callbackArgs, void *arg, int mode);
6969
void detachInterrupt(uint8_t pin);
7070

71+
unsigned long pulseIn(uint8_t pinNumber, uint8_t state, unsigned long timeout = 1000000L);
72+
unsigned long pulseInLong(uint8_t pinNumber, uint8_t state, unsigned long timeout);
7173

7274
#endif //_AP3_GPIO_H_

cores/arduino/ard_sup/gpio/ap3_gpio.cpp

Lines changed: 134 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#include "ap3_gpio.h"
22
#include "variant.h"
33

4-
typedef struct{
5-
voidFuncPtrArgs callback; // the callback function
6-
void* arg; // argument
7-
uint8_t mode; // Arduino interrupt mode
8-
uint8_t pad; // which apollo3 pad
9-
}ap3_gpio_isr_entry_t;
10-
ap3_gpio_isr_entry_t gpio_isr_entries[AP3_GPIO_MAX_PADS] = {NULL};
11-
uint8_t gpio_num_isr = 0;
4+
typedef struct
5+
{
6+
voidFuncPtrArgs callback; // the callback function
7+
void *arg; // argument
8+
uint8_t mode; // Arduino interrupt mode
9+
uint8_t pad; // which apollo3 pad
10+
} ap3_gpio_isr_entry_t;
11+
ap3_gpio_isr_entry_t gpio_isr_entries[AP3_GPIO_MAX_PADS] = {NULL};
12+
uint8_t gpio_num_isr = 0;
1213

1314
//*****************************************************************************
1415
// Local defines. Copied from am_hal_gpio.c
@@ -26,8 +27,6 @@ uint8_t gpio_num_isr = 0;
2627
#define GPIOCFG_FLD_OUTCFG_S 1
2728
#define GPIOCFG_FLD_INCFG_S 0
2829

29-
30-
3130
ap3_gpio_pad_t ap3_gpio_pin2pad(ap3_gpio_pin_t pin)
3231
{
3332
return ap3_variant_pinmap[pin];
@@ -134,21 +133,32 @@ extern "C" void am_gpio_isr(void)
134133
uint64_t gpio_int_mask = 0x00;
135134
am_hal_gpio_interrupt_status_get(true, &gpio_int_mask);
136135

137-
for(uint8_t indi = 0; indi < gpio_num_isr; indi++){
138-
if( gpio_isr_entries[indi].callback != NULL ){
139-
if( gpio_int_mask & AM_HAL_GPIO_BIT(gpio_isr_entries[indi].pad) ){
136+
for (uint8_t indi = 0; indi < gpio_num_isr; indi++)
137+
{
138+
if (gpio_isr_entries[indi].callback != NULL)
139+
{
140+
if (gpio_int_mask & AM_HAL_GPIO_BIT(gpio_isr_entries[indi].pad))
141+
{
140142
gpio_isr_entries[indi].callback(gpio_isr_entries[indi].arg);
141143
}
142-
if( !((gpio_isr_entries[indi].mode == LOW) || (gpio_isr_entries[indi].mode == HIGH)) ){ // if not a HIGH or LOW interrupt then clear the flag
144+
if (!((gpio_isr_entries[indi].mode == LOW) || (gpio_isr_entries[indi].mode == HIGH)))
145+
{ // if not a HIGH or LOW interrupt then clear the flag
143146
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(gpio_isr_entries[indi].pad));
144-
}else{ // In the case of a HIGH or LOW mode interrupt we need to manually check for the end state
145-
uint8_t val = digitalRead( gpio_isr_entries[indi].pad );
146-
if( gpio_isr_entries[indi].mode == LOW ){
147-
if( val ){
147+
}
148+
else
149+
{ // In the case of a HIGH or LOW mode interrupt we need to manually check for the end state
150+
uint8_t val = digitalRead(gpio_isr_entries[indi].pad);
151+
if (gpio_isr_entries[indi].mode == LOW)
152+
{
153+
if (val)
154+
{
148155
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(gpio_isr_entries[indi].pad));
149156
}
150-
}else{
151-
if( !val ){
157+
}
158+
else
159+
{
160+
if (!val)
161+
{
152162
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(gpio_isr_entries[indi].pad));
153163
}
154164
}
@@ -157,15 +167,21 @@ extern "C" void am_gpio_isr(void)
157167
}
158168
}
159169

160-
void attachInterruptArg(uint8_t pin, voidFuncPtrArgs callbackArgs, void * arg, int mode)
170+
void attachInterruptArg(uint8_t pin, voidFuncPtrArgs callbackArgs, void *arg, int mode)
161171
{
162172
ap3_gpio_pad_t pad = ap3_gpio_pin2pad(pin);
163-
if( pad == AP3_GPIO_PAD_UNUSED ){ return; }
173+
if (pad == AP3_GPIO_PAD_UNUSED)
174+
{
175+
return;
176+
}
164177

165-
if( gpio_num_isr < AP3_GPIO_MAX_PADS ){
178+
if (gpio_num_isr < AP3_GPIO_MAX_PADS)
179+
{
166180
uint8_t indi = 0;
167-
for(indi = 0; indi < gpio_num_isr; indi++){
168-
if(gpio_isr_entries[indi].pad == pad){
181+
for (indi = 0; indi < gpio_num_isr; indi++)
182+
{
183+
if (gpio_isr_entries[indi].pad == pad)
184+
{
169185
break;
170186
}
171187
}
@@ -177,88 +193,83 @@ void attachInterruptArg(uint8_t pin, voidFuncPtrArgs callbackArgs, void * arg, i
177193

178194
// enable interrupts for the pad in question (Arduino does this by default when attachInterrupt is called)
179195
uint8_t eIntDir = 0x00;
180-
if(( mode == FALLING ) || ( mode == LOW )){
196+
if ((mode == FALLING) || (mode == LOW))
197+
{
181198
eIntDir = AM_HAL_GPIO_PIN_INTDIR_HI2LO;
182-
}else if(( mode == RISING ) || ( mode == HIGH )){
199+
}
200+
else if ((mode == RISING) || (mode == HIGH))
201+
{
183202
eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
184-
}else{
185-
eIntDir = AM_HAL_GPIO_PIN_INTDIR_BOTH;
186203
}
187-
ap3_gpio_enable_interrupts( pad, eIntDir);
204+
else
205+
{
206+
eIntDir = AM_HAL_GPIO_PIN_INTDIR_BOTH;
207+
}
208+
ap3_gpio_enable_interrupts(pad, eIntDir);
188209

189-
// clear the flag and enable the interrupt in the NVIC
210+
// clear the flag and enable the interrupt in the NVIC
190211
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(pad));
191212
am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(pad));
192213
NVIC_EnableIRQ(GPIO_IRQn);
193214

194-
if( indi == gpio_num_isr ){
215+
if (indi == gpio_num_isr)
216+
{
195217
gpio_num_isr++;
196218
}
197219
}
198220
}
199221

200222
void attachInterrupt(uint8_t pin, voidFuncPtr callback, int mode)
201223
{
202-
attachInterruptArg( pin, (voidFuncPtrArgs)callback, NULL, mode );
224+
attachInterruptArg(pin, (voidFuncPtrArgs)callback, NULL, mode);
203225
}
204226

205227
extern void detachInterrupt(uint8_t pin)
206228
{
207229
ap3_gpio_pad_t pad = ap3_gpio_pin2pad(pin);
208-
if( pad == AP3_GPIO_PAD_UNUSED ){ return; }
230+
if (pad == AP3_GPIO_PAD_UNUSED)
231+
{
232+
return;
233+
}
209234

210235
uint8_t indi = 0;
211236

212237
// Look for an entry that matches the pad
213-
for(indi = 0; indi < gpio_num_isr; indi++){
214-
if(gpio_isr_entries[indi].pad == pad){
238+
for (indi = 0; indi < gpio_num_isr; indi++)
239+
{
240+
if (gpio_isr_entries[indi].pad == pad)
241+
{
215242
break;
216243
}
217244
}
218245

219246
// return if it was not found (prevent changes to the isr entry list)
220-
if( indi == gpio_num_isr ){
247+
if (indi == gpio_num_isr)
248+
{
221249
return;
222250
}
223251

224252
// disable the interrupt in the NVIC
225253
am_hal_gpio_interrupt_disable(AM_HAL_GPIO_BIT(pad));
226254
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(pad));
227255

228-
// disable interrupts for the given pad without blasting the configuration
229-
ap3_gpio_enable_interrupts( pad, AM_HAL_GPIO_PIN_INTDIR_NONE);
256+
// disable interrupts for the given pad without blasting the configuration
257+
ap3_gpio_enable_interrupts(pad, AM_HAL_GPIO_PIN_INTDIR_NONE);
230258

231259
// Shift down the remaining interrupt entries
232-
for(indi; indi < gpio_num_isr-1; indi++){
233-
gpio_isr_entries[indi] = gpio_isr_entries[indi+1];
260+
for (indi; indi < gpio_num_isr - 1; indi++)
261+
{
262+
gpio_isr_entries[indi] = gpio_isr_entries[indi + 1];
234263
}
235-
264+
236265
// Clear out the last entry
237266
gpio_isr_entries[gpio_num_isr].pad = 0;
238267
gpio_isr_entries[gpio_num_isr].callback = NULL;
239268
gpio_isr_entries[gpio_num_isr].mode = LOW;
240269
gpio_isr_entries[gpio_num_isr].arg = NULL;
241-
242270
}
243271

244-
245-
246-
247-
248-
249-
250-
251-
252-
253-
254-
255-
256-
257-
258-
259-
260-
261-
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir )
272+
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir)
262273
{
263274
uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg;
264275
uint32_t ui32Funcsel, ui32PowerSw;
@@ -276,7 +287,6 @@ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir )
276287
//
277288
ui32GPCfg = ui32Padreg = ui32AltPadCfg = 0;
278289

279-
280290
//
281291
// Map the requested interrupt direction settings into the Apollo3
282292
// GPIOCFG register field, which is a 4-bit field:
@@ -286,7 +296,6 @@ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir )
286296
//
287297
ui32GPCfg |= (((eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S) | (((eIntDir >> 1) & 0x1) << GPIOCFG_FLD_INCFG_S);
288298

289-
290299
//
291300
// At this point, the configuration variable, ui32GpioCfg
292301
// value is set (at bit position 0) and ready to write
@@ -326,4 +335,65 @@ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir )
326335

327336
return AM_HAL_STATUS_SUCCESS;
328337

329-
} // am_hal_gpio_pinconfig()
338+
} // am_hal_gpio_pinconfig()
339+
340+
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
341+
or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
342+
to 3 minutes in length, but must be called at least a few dozen microseconds
343+
before the start of the pulse.
344+
345+
Original Arduino function could operate in noInterrupt() context. This
346+
function cannot.
347+
*/
348+
unsigned long pulseIn(uint8_t pinNumber, uint8_t state, unsigned long timeout)
349+
{
350+
return (pulseInLong(pinNumber, state, timeout));
351+
}
352+
353+
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
354+
or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
355+
to 3 minutes in length, but must be called at least a few dozen microseconds
356+
before the start of the pulse.
357+
358+
ATTENTION: This function relies on micros() so cannot be used in noInterrupt() context
359+
*/
360+
unsigned long pulseInLong(uint8_t pinNumber, uint8_t state, unsigned long timeout)
361+
{
362+
uint8_t padNumber = ap3_gpio_pin2pad(pinNumber);
363+
364+
if (timeout > 3 * 60 * 1000000L)
365+
timeout = 3 * 60 * 1000000L; //Limit timeout to 3 minutes
366+
367+
//Enable fast GPIO for this pad
368+
am_hal_gpio_fastgpio_disable(padNumber);
369+
am_hal_gpio_fastgpio_clr(padNumber);
370+
am_hal_gpio_fast_pinconfig((uint64_t)0x1 << padNumber, g_AM_HAL_GPIO_OUTPUT_WITH_READ, 0);
371+
372+
uint32_t startMicros = micros();
373+
374+
while (am_hal_gpio_fastgpio_read(padNumber) == state) //Wait for previous pulse to end
375+
{
376+
if (micros() - startMicros > timeout)
377+
return (0); //Pulse did not end
378+
}
379+
380+
while (am_hal_gpio_fastgpio_read(padNumber) != state) //Wait for pin to change state
381+
{
382+
if (micros() - startMicros > timeout)
383+
return (0); //Pulse did not start
384+
}
385+
386+
startMicros = micros(); //Restart time
387+
388+
while (am_hal_gpio_fastgpio_read(padNumber) == state) //Wait for pin to exit sought state
389+
{
390+
if (micros() - startMicros > timeout)
391+
return (0); //Pulse did not end
392+
}
393+
394+
uint32_t stopMicros = micros();
395+
396+
am_hal_gpio_fastgpio_disable(padNumber);
397+
398+
return (stopMicros - startMicros);
399+
}

0 commit comments

Comments
 (0)