pybadc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. * Copyright (c) 2015 Daniel Campora
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include "py/runtime.h"
  30. #include "py/binary.h"
  31. #include "py/gc.h"
  32. #include "py/mperrno.h"
  33. #include "bufhelper.h"
  34. #include "inc/hw_types.h"
  35. #include "inc/hw_adc.h"
  36. #include "inc/hw_ints.h"
  37. #include "inc/hw_memmap.h"
  38. #include "rom_map.h"
  39. #include "interrupt.h"
  40. #include "pin.h"
  41. #include "gpio.h"
  42. #include "prcm.h"
  43. #include "adc.h"
  44. #include "pybadc.h"
  45. #include "pybpin.h"
  46. #include "pybsleep.h"
  47. #include "pins.h"
  48. #include "mpexception.h"
  49. /******************************************************************************
  50. DECLARE CONSTANTS
  51. ******************************************************************************/
  52. #define PYB_ADC_NUM_CHANNELS 4
  53. /******************************************************************************
  54. DEFINE TYPES
  55. ******************************************************************************/
  56. typedef struct {
  57. mp_obj_base_t base;
  58. bool enabled;
  59. } pyb_adc_obj_t;
  60. typedef struct {
  61. mp_obj_base_t base;
  62. pin_obj_t *pin;
  63. byte channel;
  64. byte id;
  65. bool enabled;
  66. } pyb_adc_channel_obj_t;
  67. /******************************************************************************
  68. DECLARE PRIVATE DATA
  69. ******************************************************************************/
  70. STATIC pyb_adc_channel_obj_t pyb_adc_channel_obj[PYB_ADC_NUM_CHANNELS] = { {.pin = &pin_GP2, .channel = ADC_CH_0, .id = 0, .enabled = false},
  71. {.pin = &pin_GP3, .channel = ADC_CH_1, .id = 1, .enabled = false},
  72. {.pin = &pin_GP4, .channel = ADC_CH_2, .id = 2, .enabled = false},
  73. {.pin = &pin_GP5, .channel = ADC_CH_3, .id = 3, .enabled = false} };
  74. STATIC pyb_adc_obj_t pyb_adc_obj = {.enabled = false};
  75. STATIC const mp_obj_type_t pyb_adc_channel_type;
  76. /******************************************************************************
  77. DECLARE PRIVATE FUNCTIONS
  78. ******************************************************************************/
  79. STATIC mp_obj_t adc_channel_deinit(mp_obj_t self_in);
  80. /******************************************************************************
  81. DEFINE PUBLIC FUNCTIONS
  82. ******************************************************************************/
  83. STATIC void pyb_adc_init (pyb_adc_obj_t *self) {
  84. // enable and configure the timer
  85. MAP_ADCTimerConfig(ADC_BASE, (1 << 17) - 1);
  86. MAP_ADCTimerEnable(ADC_BASE);
  87. // enable the ADC peripheral
  88. MAP_ADCEnable(ADC_BASE);
  89. self->enabled = true;
  90. }
  91. STATIC void pyb_adc_check_init(void) {
  92. // not initialized
  93. if (!pyb_adc_obj.enabled) {
  94. mp_raise_OSError(MP_EPERM);
  95. }
  96. }
  97. STATIC void pyb_adc_channel_init (pyb_adc_channel_obj_t *self) {
  98. // the ADC block must be enabled first
  99. pyb_adc_check_init();
  100. // configure the pin in analog mode
  101. pin_config (self->pin, -1, PIN_TYPE_ANALOG, PIN_TYPE_STD, -1, PIN_STRENGTH_2MA);
  102. // enable the ADC channel
  103. MAP_ADCChannelEnable(ADC_BASE, self->channel);
  104. self->enabled = true;
  105. }
  106. STATIC void pyb_adc_deinit_all_channels (void) {
  107. for (int i = 0; i < PYB_ADC_NUM_CHANNELS; i++) {
  108. adc_channel_deinit(&pyb_adc_channel_obj[i]);
  109. }
  110. }
  111. /******************************************************************************/
  112. /* MicroPython bindings : adc object */
  113. STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
  114. pyb_adc_obj_t *self = self_in;
  115. if (self->enabled) {
  116. mp_printf(print, "ADC(0, bits=12)");
  117. } else {
  118. mp_printf(print, "ADC(0)");
  119. }
  120. }
  121. STATIC const mp_arg_t pyb_adc_init_args[] = {
  122. { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
  123. { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 12} },
  124. };
  125. STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
  126. // parse args
  127. mp_map_t kw_args;
  128. mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
  129. mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_init_args)];
  130. mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_adc_init_args, args);
  131. // check the peripheral id
  132. if (args[0].u_int != 0) {
  133. mp_raise_OSError(MP_ENODEV);
  134. }
  135. // check the number of bits
  136. if (args[1].u_int != 12) {
  137. mp_raise_ValueError(mpexception_value_invalid_arguments);
  138. }
  139. // setup the object
  140. pyb_adc_obj_t *self = &pyb_adc_obj;
  141. self->base.type = &pyb_adc_type;
  142. // initialize and register with the sleep module
  143. pyb_adc_init(self);
  144. pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_adc_init);
  145. return self;
  146. }
  147. STATIC mp_obj_t adc_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
  148. // parse args
  149. mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_init_args) - 1];
  150. mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_adc_init_args[1], args);
  151. // check the number of bits
  152. if (args[0].u_int != 12) {
  153. mp_raise_ValueError(mpexception_value_invalid_arguments);
  154. }
  155. pyb_adc_init(pos_args[0]);
  156. return mp_const_none;
  157. }
  158. STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adc_init_obj, 1, adc_init);
  159. STATIC mp_obj_t adc_deinit(mp_obj_t self_in) {
  160. pyb_adc_obj_t *self = self_in;
  161. // first deinit all channels
  162. pyb_adc_deinit_all_channels();
  163. MAP_ADCDisable(ADC_BASE);
  164. self->enabled = false;
  165. // unregister it with the sleep module
  166. pyb_sleep_remove ((const mp_obj_t)self);
  167. return mp_const_none;
  168. }
  169. STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_deinit_obj, adc_deinit);
  170. STATIC mp_obj_t adc_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
  171. STATIC const mp_arg_t pyb_adc_channel_args[] = {
  172. { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
  173. { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
  174. };
  175. // parse args
  176. mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_channel_args)];
  177. mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_adc_channel_args, args);
  178. uint ch_id;
  179. if (args[0].u_obj != MP_OBJ_NULL) {
  180. ch_id = mp_obj_get_int(args[0].u_obj);
  181. if (ch_id >= PYB_ADC_NUM_CHANNELS) {
  182. mp_raise_ValueError(mpexception_value_invalid_arguments);
  183. } else if (args[1].u_obj != mp_const_none) {
  184. uint pin_ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
  185. if (ch_id != pin_ch_id) {
  186. mp_raise_ValueError(mpexception_value_invalid_arguments);
  187. }
  188. }
  189. } else {
  190. ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
  191. }
  192. // setup the object
  193. pyb_adc_channel_obj_t *self = &pyb_adc_channel_obj[ch_id];
  194. self->base.type = &pyb_adc_channel_type;
  195. pyb_adc_channel_init (self);
  196. // register it with the sleep module
  197. pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_adc_channel_init);
  198. return self;
  199. }
  200. STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adc_channel_obj, 1, adc_channel);
  201. STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
  202. { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&adc_init_obj) },
  203. { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&adc_deinit_obj) },
  204. { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&adc_channel_obj) },
  205. };
  206. STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
  207. const mp_obj_type_t pyb_adc_type = {
  208. { &mp_type_type },
  209. .name = MP_QSTR_ADC,
  210. .print = adc_print,
  211. .make_new = adc_make_new,
  212. .locals_dict = (mp_obj_t)&adc_locals_dict,
  213. };
  214. STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
  215. pyb_adc_channel_obj_t *self = self_in;
  216. if (self->enabled) {
  217. mp_printf(print, "ADCChannel(%u, pin=%q)", self->id, self->pin->name);
  218. } else {
  219. mp_printf(print, "ADCChannel(%u)", self->id);
  220. }
  221. }
  222. STATIC mp_obj_t adc_channel_init(mp_obj_t self_in) {
  223. pyb_adc_channel_obj_t *self = self_in;
  224. // re-enable it
  225. pyb_adc_channel_init(self);
  226. return mp_const_none;
  227. }
  228. STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_init_obj, adc_channel_init);
  229. STATIC mp_obj_t adc_channel_deinit(mp_obj_t self_in) {
  230. pyb_adc_channel_obj_t *self = self_in;
  231. MAP_ADCChannelDisable(ADC_BASE, self->channel);
  232. // unregister it with the sleep module
  233. pyb_sleep_remove ((const mp_obj_t)self);
  234. self->enabled = false;
  235. return mp_const_none;
  236. }
  237. STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_deinit_obj, adc_channel_deinit);
  238. STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
  239. pyb_adc_channel_obj_t *self = self_in;
  240. uint32_t value;
  241. // the channel must be enabled
  242. if (!self->enabled) {
  243. mp_raise_OSError(MP_EPERM);
  244. }
  245. // wait until a new value is available
  246. while (!MAP_ADCFIFOLvlGet(ADC_BASE, self->channel));
  247. // read the sample
  248. value = MAP_ADCFIFORead(ADC_BASE, self->channel);
  249. // the 12 bit sampled value is stored in bits [13:2]
  250. return MP_OBJ_NEW_SMALL_INT((value & 0x3FFF) >> 2);
  251. }
  252. STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_value_obj, adc_channel_value);
  253. STATIC mp_obj_t adc_channel_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  254. mp_arg_check_num(n_args, n_kw, 0, 0, false);
  255. return adc_channel_value (self_in);
  256. }
  257. STATIC const mp_rom_map_elem_t adc_channel_locals_dict_table[] = {
  258. { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&adc_channel_init_obj) },
  259. { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&adc_channel_deinit_obj) },
  260. { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&adc_channel_value_obj) },
  261. };
  262. STATIC MP_DEFINE_CONST_DICT(adc_channel_locals_dict, adc_channel_locals_dict_table);
  263. STATIC const mp_obj_type_t pyb_adc_channel_type = {
  264. { &mp_type_type },
  265. .name = MP_QSTR_ADCChannel,
  266. .print = adc_channel_print,
  267. .call = adc_channel_call,
  268. .locals_dict = (mp_obj_t)&adc_channel_locals_dict,
  269. };