3838#include <bluetooth/uuid.h>
3939#include <bluetooth/gatt.h>
4040
41+ #include <gpio.h>
42+ #include <sys_clock.h>
43+
4144QUARK_SE_IPM_DEFINE (temperature_ipm , 0 , QUARK_SE_IPM_INBOUND );
4245
4346#define BT_UUID_WEBBT BT_UUID_DECLARE_16(0xfc00)
@@ -53,7 +56,7 @@ static uint8_t simulate_blvl;
5356static uint8_t temperature = 20 ;
5457static uint8_t rgb [3 ] = {0xff , 0x00 , 0x00 }; // red
5558
56- struct device * pwm , * tmp36 ;
59+ struct device * pwm , * tmp36 , * tmp2302 ;
5760#define IO3_RED 0
5861#define IO5_GREEN 1
5962#define IO6_BLUE 2
@@ -65,6 +68,22 @@ struct device *pwm, *tmp36;
6568#define PERIOD 64000
6669#define MAX (a ,b ) (((a)>(b))?(a):(b))
6770
71+ #if defined(CONFIG_GPIO_DW_0 )
72+ #define GPIO_DRV_NAME CONFIG_GPIO_DW_0_NAME
73+ #elif defined(CONFIG_GPIO_QMSI_0 )
74+ #define GPIO_DRV_NAME CONFIG_GPIO_QMSI_0_NAME
75+ #elif defined(CONFIG_GPIO_ATMEL_SAM3 )
76+ #define GPIO_DRV_NAME CONFIG_GPIO_ATMEL_SAM3_PORTB_DEV_NAME
77+ #elif
78+ #define GPIO_DRV_NAME "GPIO_0"
79+ #endif
80+
81+ #define IO8_AM2302 16
82+
83+ uint32_t start_time ;
84+ uint32_t stop_time ;
85+ uint32_t cycles_spent ;
86+
6887void pwm_write (void )
6988{
7089 uint32_t r_on , g_on , b_on ;
@@ -160,9 +179,145 @@ void temperature_ipm_callback(void *context, uint32_t id, volatile void *data)
160179 bt_gatt_notify (conn , & attrs [2 ], & temperature , sizeof (temperature ));
161180}
162181
182+ uint32_t measure_signal (uint32_t signal )
183+ {
184+ uint32_t count = 1 ;
185+
186+ uint32_t readValue ;
187+
188+ start_time = sys_cycle_get_32 ();
189+
190+ do {
191+ gpio_pin_read (tmp2302 , IO8_AM2302 , & readValue );
192+ if (count ++ > 255 ) return -1 ;
193+ } while (readValue == signal );
194+
195+ stop_time = sys_cycle_get_32 ();
196+
197+ cycles_spent = stop_time - start_time ;
198+ return SYS_CLOCK_HW_CYCLES_TO_NS (cycles_spent ) / 1000 ; // Microseconds
199+ }
200+
201+ int verifyResponse (uint32_t response )
202+ {
203+ if (response >= 75 && response <= 85 )
204+ return 1 ;
205+ return -1 ;
206+ }
207+
208+ int verifyLowSignal (uint32_t low )
209+ {
210+ if (low >= 48 && low <= 55 )
211+ return 1 ;
212+ return -1 ;
213+ }
214+
215+ int checkHighSignal (uint32_t high )
216+ {
217+ if (high >= 68 && high <= 75 )
218+ return 1 ;
219+ if (high >= 22 && high <= 30 )
220+ return 0 ;
221+ return -1 ;
222+ }
223+
224+ void read_am2302_tmp ()
225+ {
226+ uint32_t cycles [80 ];
227+
228+ gpio_pin_configure (tmp2302 , IO8_AM2302 , (GPIO_DIR_OUT ));
229+ gpio_pin_write (tmp2302 , IO8_AM2302 , 1 );
230+ task_sleep (USEC (1000 ));
231+
232+ // STEP 1+2
233+
234+ // We set MCU to output.
235+ // Due to previous pullup, it should always be high.
236+
237+ // We signal the AM2302 to wake up, by signaling
238+ // low for min 800us, but typically 1ms. (max 20ms).
239+ gpio_pin_write (tmp2302 , IO8_AM2302 , 0 );
240+ task_sleep (USEC (1000 ));
241+
242+ // End the start signal by setting data line high for 40 microseconds.
243+ gpio_pin_write (tmp2302 , IO8_AM2302 , 1 );
244+ task_sleep (USEC (40 ));
245+
246+ // Then set MCU to input and release the bus
247+ // Due to pullup, it will go high and it will take
248+ // at least 20us, though typically 30ns and
249+ // max 200ns for the AM2302 to signal low.
250+ gpio_pin_configure (tmp2302 , IO8_AM2302 , (GPIO_DIR_IN ));
251+ task_sleep (USEC (10 ));
252+
253+ // Signal from AM2302 that it is ready to send data.
254+
255+ uint32_t time ;
256+
257+ time = measure_signal (0 );
258+ if (verifyResponse (time ) < 0 )
259+ printk ("Response low time not within limits: %d\n" , time );
260+ time = measure_signal (1 );
261+ if (verifyResponse (time ) < 0 )
262+ printk ("Response high time not within limits: %d\n" , time );
263+
264+ // Read data.
265+ for (int i = 0 ; i < 80 ; i += 2 ) {
266+ cycles [i ] = measure_signal (0 );
267+ cycles [i + 1 ] = measure_signal (1 );
268+ }
269+
270+ // -- Timing critical code is now over. --
271+
272+ uint8_t dataset [5 ];
273+
274+ // Each data set is 5 bytes (5 * 8 = 40)
275+ for (int i = 0 ; i < 40 ; ++ i ) {
276+ uint32_t low = cycles [2 * i ];
277+ uint32_t high = cycles [2 * i + 1 ];
278+
279+ dataset [i /8 ] <<= 1 ; // Move existing value one bit.
280+
281+ int lowstate = verifyLowSignal (low );
282+ int highstate = checkHighSignal (high );
283+
284+ if (highstate == 1 )
285+ dataset [i /8 ] |= 1 ;
286+
287+ if (lowstate < 0 || highstate < 0 ) printk ("X: " ); else printk ("%d: " , highstate );
288+ printk ("low" ); if (lowstate < 0 ) printk ("*" ); printk ("\t: %d\t/\t" , low );
289+ printk ("high" ); if (highstate < 0 ) printk ("*" ); printk ("\t: %d\n" , high );
290+ if ((i + 1 ) % 8 == 0 ) printk ("\n" );
291+ }
292+
293+ // Debugging:
294+ for (int j = 0 ; j < 5 ; j ++ ){
295+ printk ("%d " , dataset [j ]);
296+ }
297+ printk ("\n" );
298+
299+ // Checksum check:
300+ if (dataset [4 ] != ((dataset [0 ] + dataset [1 ] + dataset [2 ] + dataset [3 ]) & 0xFF )) {
301+ printk ("Checksum failed!\n" );
302+ }
303+
304+ float humidity = (float ) (dataset [0 ] << 8 | dataset [1 ]) / 10.0 ;
305+ printk ("Humidity: %f \n" , humidity );
306+ float temperature ;
307+
308+ int neg = dataset [2 ] & 0x80 ; // higtest bit only.
309+ dataset [2 ] &= 0x7F ; // Remove highest bit.
310+
311+ temperature = (float ) (dataset [2 ] << 8 | dataset [3 ]) / 10.0 ;
312+ if (neg > 0 )
313+ temperature *= -1 ;
314+
315+ printk ("Temperature: %f \n" , temperature );
316+ }
317+
163318void service_init (struct bt_conn * conn )
164319{
165- if ((pwm = device_get_binding ("PWM " )) == NULL )
320+ if ((pwm = device_get_binding ("PWM_0 " )) == NULL )
166321 printk ("device_get_binding: failed for PWM\n" );
167322 else {
168323 pwm_write ();
@@ -176,4 +331,10 @@ void service_init(struct bt_conn *conn)
176331 ipm_set_enabled (ipm , 1 );
177332
178333 bt_gatt_register (attrs , ARRAY_SIZE (attrs ));
334+
335+ if ((tmp2302 = device_get_binding (GPIO_DRV_NAME )) == NULL )
336+ printk ("device_get_binding: failed for TMP2302\n" );
337+ else {
338+ read_am2302_tmp ();
339+ }
179340}
0 commit comments