28
28
#include <stdint.h>
29
29
#include "py/obj.h"
30
30
#include "py/runtime.h"
31
+ #include "py/mperrno.h"
31
32
#include "py/mphal.h"
32
33
33
34
#include "sam.h"
@@ -45,6 +46,7 @@ typedef struct _dac_obj_t {
45
46
uint8_t vref ;
46
47
int8_t dma_channel ;
47
48
int8_t tc_index ;
49
+ bool busy ;
48
50
uint32_t count ;
49
51
mp_obj_t callback ;
50
52
} dac_obj_t ;
@@ -62,8 +64,8 @@ STATIC dac_obj_t dac_obj[] = {
62
64
#elif defined(MCU_SAMD51 )
63
65
64
66
STATIC dac_obj_t dac_obj [] = {
65
- {{& machine_dac_type }, 0 , 0 , PIN_PA02 , 2 , -1 , -1 , 1 , NULL },
66
- {{& machine_dac_type }, 1 , 0 , PIN_PA05 , 2 , -1 , -1 , 1 , NULL },
67
+ {{& machine_dac_type }, 0 , 0 , PIN_PA02 , 2 , -1 , -1 , false, 1 , NULL },
68
+ {{& machine_dac_type }, 1 , 0 , PIN_PA05 , 2 , -1 , -1 , false, 1 , NULL },
67
69
};
68
70
// According to Errata 2.9.2, VDDANA as ref value is not available. However it worked
69
71
// in tests. So I keep the selection here but set the default to Aref, which is usually
@@ -94,6 +96,7 @@ void dac_irq_handler(int dma_channel) {
94
96
dma_desc [self -> dma_channel ].BTCTRL .reg |= DMAC_BTCTRL_VALID ;
95
97
DMAC -> CHCTRLA .reg |= DMAC_CHCTRLA_ENABLE ;
96
98
} else {
99
+ self -> busy = false;
97
100
if (self -> callback != MP_OBJ_NULL ) {
98
101
mp_sched_schedule (self -> callback , self );
99
102
}
@@ -111,6 +114,7 @@ void dac_irq_handler(int dma_channel) {
111
114
dma_desc [self -> dma_channel ].BTCTRL .reg |= DMAC_BTCTRL_VALID ;
112
115
DMAC -> Channel [self -> dma_channel ].CHCTRLA .reg |= DMAC_CHCTRLA_ENABLE ;
113
116
} else {
117
+ self -> busy = false;
114
118
if (self -> callback != MP_OBJ_NULL ) {
115
119
mp_sched_schedule (self -> callback , self );
116
120
}
@@ -215,6 +219,10 @@ STATIC void dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
215
219
STATIC mp_obj_t dac_write (mp_obj_t self_in , mp_obj_t value_in ) {
216
220
Dac * dac = dac_bases [0 ]; // Just one DAC
217
221
dac_obj_t * self = self_in ;
222
+ if (self -> busy != false) {
223
+ mp_raise_OSError (MP_EBUSY );
224
+ }
225
+
218
226
int value = mp_obj_get_int (value_in );
219
227
220
228
if (value < 0 || value > MAX_DAC_VALUE ) {
@@ -257,6 +265,8 @@ STATIC mp_obj_t dac_write_timed(size_t n_args, const mp_obj_t *args) {
257
265
}
258
266
// Configure TC; no need to check the return value
259
267
configure_tc (self -> tc_index , freq , 0 );
268
+ self -> busy = true;
269
+
260
270
// Configure DMA for halfword output to the DAC
261
271
#if defined(MCU_SAMD21 )
262
272
@@ -335,10 +345,18 @@ STATIC mp_obj_t dac_deinit(mp_obj_t self_in) {
335
345
self -> tc_index = -1 ;
336
346
}
337
347
self -> callback = MP_OBJ_NULL ;
348
+ self -> busy = false;
338
349
return mp_const_none ;
339
350
}
340
351
MP_DEFINE_CONST_FUN_OBJ_1 (dac_deinit_obj , dac_deinit );
341
352
353
+ // busy() : Report, if the DAC device is busy
354
+ STATIC mp_obj_t machine_dac_busy (mp_obj_t self_in ) {
355
+ dac_obj_t * self = MP_OBJ_TO_PTR (self_in );
356
+ return self -> busy ? mp_const_true : mp_const_false ;
357
+ }
358
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_dac_busy_obj , machine_dac_busy );
359
+
342
360
// Clear the DMA channel entry in the DAC object.
343
361
void dac_deinit_channel (void ) {
344
362
dac_obj [0 ].dma_channel = -1 ;
@@ -348,6 +366,7 @@ void dac_deinit_channel(void) {
348
366
}
349
367
350
368
STATIC const mp_rom_map_elem_t dac_locals_dict_table [] = {
369
+ { MP_ROM_QSTR (MP_QSTR_busy ), MP_ROM_PTR (& machine_dac_busy_obj ) },
351
370
{ MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& dac_deinit_obj ) },
352
371
{ MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& dac_write_obj ) },
353
372
{ MP_ROM_QSTR (MP_QSTR_write_timed ), MP_ROM_PTR (& dac_write_timed_obj ) },
0 commit comments