#include #include #include #include /* Private */ #include "adc.h" typedef struct { uint32_t channel; uint32_t avg; } mrb_adc_t; static void mrb_adc_free(mrb_state *mrb, void *ptr); const struct mrb_data_type mrb_adc_type = { .struct_name = "ADC", .dfree = mrb_adc_free, }; static void mrb_adc_free(mrb_state *mrb, void *ptr) { mrb_free(mrb, ptr); } static mrb_value mrb_adc_initialize(mrb_state *mrb, mrb_value self) { mrb_int channel_id; mrb_value init_cfg; uint32_t avg = 1; mrb_int nargs = mrb_get_args(mrb, "i|H", &channel_id, &init_cfg); if (nargs == 2) { mrb_ensure_hash_type(mrb, init_cfg); mrb_value ch_average = mrb_hash_get(mrb, init_cfg, mrb_symbol_value(mrb_intern_static(mrb, "average", 7))); if (!mrb_nil_p(ch_average)) { mrb_ensure_integer_type(mrb, ch_average); avg = mrb_integer(ch_average); } } mrb_adc_t *adc_ch = mrb_malloc(mrb, sizeof(mrb_adc_t)); if (adc_ch == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to allocate ADC struct"); } adc_ch->channel = channel_id; adc_ch->avg = avg; mrb_machine_adc_impl_config(adc_ch->channel); DATA_PTR(self) = adc_ch; DATA_TYPE(self) = &mrb_adc_type; return self; } static mrb_value mrb_adc_value(mrb_state *mrb, mrb_value self) { mrb_adc_t *adc_ch = mrb_data_get_ptr(mrb, self, &mrb_adc_type); if (adc_ch == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized ADC struct"); } uint32_t adc_uv = 0; for (uint32_t i = 0; i < adc_ch->avg; i++) { adc_uv += mrb_machine_adc_impl_read(adc_ch->channel); } adc_uv = adc_uv / adc_ch->avg; return mrb_int_value(mrb, adc_uv); } void mrb_machine_adc_gem_init(mrb_state *mrb) { /** * Example: * analog_ch = Machine::ADC.new(0, {average: 4}) * analog_ch.value */ struct RClass *module_machine = mrb_define_module(mrb, "Machine"); struct RClass *class_adc = mrb_define_class_under(mrb, module_machine, "ADC", mrb->object_class); MRB_SET_INSTANCE_TT(class_adc, MRB_TT_CDATA); mrb_define_method(mrb, class_adc, "initialize", mrb_adc_initialize, MRB_ARGS_ARG(1, 1)); mrb_define_method(mrb, class_adc, "value", mrb_adc_value, MRB_ARGS_NONE()); } void mrb_machine_adc_gem_final(mrb_state *mrb) { /* Unused */ }