3
3
*
4
4
* The MIT License (MIT)
5
5
*
6
- * Copyright (c) 2017- 2021 Scott Shawcroft for Adafruit Industries
6
+ * Copyright (c) 2021 Dave Putz for Adafruit Industries
7
7
*
8
8
* Permission is hereby granted, free of charge, to any person obtaining a copy
9
9
* of this software and associated documentation files (the "Software"), to deal
29
29
30
30
#include <stdint.h>
31
31
32
- #include "background.h"
33
- #include "mpconfigport.h"
34
- #include "py/gc.h"
35
32
#include "py/runtime.h"
36
33
#include "shared-bindings/microcontroller/__init__.h"
37
34
#include "shared-bindings/pulseio/PulseIn.h"
43
40
pulseio_pulsein_obj_t * save_self ;
44
41
45
42
#define NO_PIN 0xff
46
-
47
- const uint16_t pulsein_program [] = {
48
- // wait 0 pin, 0 ; Wait for first low to start
49
- 0x2020 ,
50
- // irq wait 0 ; set IRQ 0 and wait
51
- 0xc020 ,
52
- // .bitloop
53
- // in pins, 1 [1] ; sample every 3 cycles (2 instructions, 1 delay)
54
- 0x4101 ,
55
- // jmp bitloop
56
- 0x0002 ,
43
+ volatile bool last_level ;
44
+ volatile uint16_t level_count = 0 ;
45
+ volatile uint16_t result = 0 ;
46
+ volatile uint16_t buf_index = 0 ;
47
+
48
+ uint16_t pulsein_program [] = {
49
+ 0x2020 , // 0: wait 0 pin, 0
50
+ 0xe03f , // 1: set x, 31
51
+ 0x4001 , // 2: in pins, 1
52
+ 0x0042 , // 3: jmp x--, 2
53
+ 0x8060 , // 4: push iffull block
54
+ 0xc020 , // 5: irq wait 0
55
+ 0x0001 , // 6: jmp 1
57
56
};
58
57
59
58
void common_hal_pulseio_pulsein_construct (pulseio_pulsein_obj_t * self ,
@@ -69,19 +68,23 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
69
68
self -> start = 0 ;
70
69
self -> len = 0 ;
71
70
save_self = self ;
71
+ // change initial state machine wait if idle_state is false
72
+ if (idle_state == false) {
73
+ pulsein_program [0 ] = 0x20a0 ;
74
+ }
72
75
73
76
// Set everything up.
74
77
rp2pio_statemachine_obj_t state_machine ;
75
78
76
79
bool ok = rp2pio_statemachine_construct (& state_machine ,
77
80
pulsein_program , sizeof (pulsein_program ) / sizeof (pulsein_program [0 ]),
78
- 125000 * 4 ,
81
+ 1000000 * 3 ,
79
82
NULL , 0 ,
80
83
NULL , 0 ,
81
84
pin , 1 ,
82
85
NULL , 0 ,
83
86
NULL , 0 ,
84
- 1 , self -> pin ,
87
+ 1 , 0 ,
85
88
1 << self -> pin , false, true,
86
89
false, 8 , false, // TX, unused
87
90
false,
@@ -96,17 +99,22 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
96
99
} else {
97
100
self -> pio_interrupt = PIO1_IRQ_0 ;
98
101
}
102
+ pio_sm_clear_fifos (self -> state_machine .pio ,self -> state_machine .state_machine );
103
+ last_level = self -> idle_state ;
104
+ level_count = 0 ;
105
+ result = 0 ;
106
+ buf_index = 0 ;
99
107
100
- pio_sm_set_in_pins (self -> state_machine .pio ,self -> state_machine .state_machine ,pin -> number );
101
- pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , false);
108
+ pio_sm_set_in_pins (state_machine .pio ,state_machine .state_machine ,pin -> number );
109
+ pio_sm_set_enabled (state_machine .pio ,state_machine .state_machine , false);
102
110
irq_set_exclusive_handler (self -> pio_interrupt , common_hal_pulseio_pulsein_interrupt );
103
- irq_set_enabled (self -> pio_interrupt , true);
104
- hw_clear_bits (& self -> state_machine .pio -> inte0 , 1u << self -> state_machine .state_machine );
105
- hw_set_bits (& self -> state_machine .pio -> inte0 , 1u << (self -> state_machine .state_machine + 8 ));
106
- // exec a set pindirs to 0 for input
107
- pio_sm_exec (self -> state_machine .pio ,self -> state_machine .state_machine ,0xe080 );
108
- pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , true);
111
+ hw_clear_bits (& state_machine .pio -> inte0 , 1u << state_machine .state_machine );
112
+ hw_set_bits (& state_machine .pio -> inte0 , 1u << (state_machine .state_machine + 8 ));
109
113
114
+ // exec a set pindirs to 0 for input
115
+ pio_sm_exec (state_machine .pio ,state_machine .state_machine ,0xe080 );
116
+ irq_set_enabled (self -> pio_interrupt , true);
117
+ pio_sm_set_enabled (state_machine .pio , state_machine .state_machine , true);
110
118
}
111
119
112
120
bool common_hal_pulseio_pulsein_deinited (pulseio_pulsein_obj_t * self ) {
@@ -131,48 +139,48 @@ void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
131
139
void common_hal_pulseio_pulsein_interrupt () {
132
140
133
141
pulseio_pulsein_obj_t * self = save_self ;
134
- // clear interrupt
135
- hw_clear_bits (& self -> state_machine .pio -> inte0 , 1u << self -> state_machine .state_machine );
136
- self -> state_machine .pio -> irq = 1u << self -> state_machine .state_machine ;
137
- irq_clear (self -> pio_interrupt );
138
- pio_sm_clear_fifos (self -> state_machine .pio ,self -> state_machine .state_machine );
139
- bool last_level = true;
140
- uint level_count = 0 ;
141
- uint16_t result = 0 ;
142
- uint16_t buf_index = 0 ;
143
- while ( buf_index < self -> maxlen ) {
144
- uint32_t rxfifo = 0 ;
145
- rxfifo = pio_sm_get_blocking (self -> state_machine .pio , self -> state_machine .state_machine );
146
- // translate from fifo to buffer
147
- for (uint i = 0 ; i < 32 ; i ++ ) {
148
- bool level = (rxfifo & (1 << i )) >> i ;
149
- if (level == last_level ) {
150
- level_count ++ ;
151
- } else {
152
- result = level_count * 6 ;
153
- last_level = level ;
154
- level_count = 1 ;
142
+ uint32_t rxfifo = 0 ;
143
+
144
+ rxfifo = pio_sm_get_blocking (self -> state_machine .pio , self -> state_machine .state_machine );
145
+ // translate from fifo to buffer
146
+ for (uint i = 0 ; i < 32 ; i ++ ) {
147
+ bool level = (rxfifo & (1 << i )) >> i ;
148
+ if (level == last_level ) {
149
+ level_count ++ ;
150
+ } else {
151
+ result = level_count ;
152
+ last_level = level ;
153
+ level_count = 1 ;
155
154
// ignore pulses that are too long and too short
156
- if (result < 10000 && result > 10 ) {
155
+ if (result < 2000 && result > 10 ) {
157
156
self -> buffer [buf_index ] = result ;
158
157
buf_index ++ ;
159
158
self -> len ++ ;
160
159
}
161
160
}
162
161
}
163
- // check for a pulse thats too long (20ms)
164
- if ( level_count > 3000 ) {
165
- break ;
166
- }
162
+ gpio_put (pin_GPIO15 .number , true);
163
+ // clear interrupt
164
+ irq_clear (self -> pio_interrupt );
165
+ hw_clear_bits (& self -> state_machine .pio -> inte0 , 1u << self -> state_machine .state_machine );
166
+ self -> state_machine .pio -> irq = 1u << self -> state_machine .state_machine ;
167
+ // check for a pulse thats too long (2000 us) and reset
168
+ if ( level_count > 2000 ) {
169
+ pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , false);
170
+ pio_sm_init (self -> state_machine .pio , self -> state_machine .state_machine , self -> state_machine .offset , & self -> state_machine .sm_config );
171
+ pio_sm_restart (self -> state_machine .pio ,self -> state_machine .state_machine );
172
+ pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , true);
173
+ irq_set_enabled (self -> pio_interrupt , true);
167
174
}
168
- pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , false);
169
- pio_sm_init (self -> state_machine .pio , self -> state_machine .state_machine , self -> state_machine .offset , & self -> state_machine .sm_config );
170
- pio_sm_restart (self -> state_machine .pio ,self -> state_machine .state_machine );
171
- pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , true);
172
- irq_set_enabled (self -> pio_interrupt , true);
173
175
}
174
176
void common_hal_pulseio_pulsein_resume (pulseio_pulsein_obj_t * self ,
175
177
uint16_t trigger_duration ) {
178
+ // exec a wait for the selected pin to change state
179
+ if (self -> idle_state == true ) {
180
+ pio_sm_exec (self -> state_machine .pio ,self -> state_machine .state_machine ,0x20a0 );
181
+ } else {
182
+ pio_sm_exec (self -> state_machine .pio ,self -> state_machine .state_machine ,0x2020 );
183
+ }
176
184
// Send the trigger pulse.
177
185
if (trigger_duration > 0 ) {
178
186
gpio_set_function (self -> pin ,GPIO_FUNC_SIO );
@@ -186,8 +194,6 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
186
194
common_hal_mcu_delay_us (100 );
187
195
gpio_set_function (self -> pin , GPIO_FUNC_PIO0 );
188
196
pio_sm_set_enabled (self -> state_machine .pio , self -> state_machine .state_machine , true);
189
- // exec a wait for the selected pin to go high
190
- pio_sm_exec (self -> state_machine .pio ,self -> state_machine .state_machine ,0x20a0 );
191
197
}
192
198
193
199
void common_hal_pulseio_pulsein_clear (pulseio_pulsein_obj_t * self ) {
@@ -202,9 +208,11 @@ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
202
208
uint16_t value = self -> buffer [self -> start ];
203
209
self -> start = (self -> start + 1 ) % self -> maxlen ;
204
210
self -> len -- ;
211
+ // if we are empty reset buffer pointer and counters
205
212
if (self -> len == 0 ) {
206
- // reset buffer pointer
207
213
self -> start = 0 ;
214
+ buf_index = 0 ;
215
+ level_count = 0 ;
208
216
}
209
217
return value ;
210
218
}
0 commit comments