Refined GPIO class.

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-03-14 22:55:41 +08:00
parent 3e175303e5
commit 12b520e787
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
2 changed files with 119 additions and 14 deletions

View File

@ -1,4 +1,5 @@
#include <mruby.h>
#include <mruby/class.h>
#include <mruby/data.h>
#include <mruby/hash.h>
#include <stdbool.h>
@ -26,33 +27,38 @@ static mrb_value mrb_gpio_initialize(mrb_state *mrb, mrb_value self) {
mrb_value init_cfg = mrb_get_arg1(mrb);
mrb_ensure_hash_type(mrb, init_cfg);
printf("Hash check passed.\n");
machine_gpio_mode_t init_mode = MACHINE_GPIO_MODE_INPUT;
machine_gpio_value_t init_value = MACHINE_GPIO_LOW;
machine_gpio_pull_t init_pull = MACHINE_GPIO_PULL_NONE;
mrb_value pin_num = mrb_hash_get(mrb, init_cfg, mrb_str_new_cstr(mrb, "pin"));
mrb_value pin_num = mrb_hash_get(mrb, init_cfg, mrb_symbol_value(mrb_intern_static(mrb, "pin", 3)));
mrb_ensure_integer_type(mrb, pin_num);
printf("Pin: %ld\n", mrb_integer(pin_num));
/* Optional parameters, use default if not received from hash */
mrb_value pin_mode = mrb_hash_get(mrb, init_cfg, mrb_str_new_cstr(mrb, "mode"));
mrb_value pin_mode = mrb_hash_get(mrb, init_cfg, mrb_symbol_value(mrb_intern_static(mrb, "mode", 4)));
if (!mrb_nil_p(pin_mode)) {
mrb_ensure_integer_type(mrb, pin_mode);
init_mode = mrb_integer(pin_mode);
if (init_mode >= MACHINE_GPIO_MODE_END) {
mrb_raise(mrb, mrb->object_class, "Invalid GPIO mode");
mrb_raise(mrb, E_ARGUMENT_ERROR, "Invalid GPIO mode");
}
}
mrb_value pin_pull = mrb_hash_get(mrb, init_cfg, mrb_str_new_cstr(mrb, "pull"));
mrb_value pin_pull = mrb_hash_get(mrb, init_cfg, mrb_symbol_value(mrb_intern_static(mrb, "pull", 4)));
if (!mrb_nil_p(pin_pull)) {
mrb_ensure_integer_type(mrb, pin_pull);
init_pull = mrb_integer(pin_pull);
if (init_pull >= MACHINE_GPIO_PULL_END) {
mrb_raise(mrb, mrb->object_class, "Invalid GPIO pull");
mrb_raise(mrb, E_ARGUMENT_ERROR, "Invalid GPIO pull");
}
}
mrb_value pin_initial_value = mrb_hash_get(mrb, init_cfg, mrb_symbol_value(mrb_intern_static(mrb, "init", 4)));
if (!mrb_nil_p(pin_initial_value)) {
mrb_ensure_integer_type(mrb, pin_initial_value);
init_value = mrb_integer(pin_initial_value);
if (init_value >= MACHINE_GPIO_END) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "Invalid GPIO initial value");
}
}
@ -60,7 +66,7 @@ static mrb_value mrb_gpio_initialize(mrb_state *mrb, mrb_value self) {
mrb_gpio_t *pin = mrb_malloc(mrb, sizeof(mrb_gpio_t));
pin->pin = mrb_integer(pin_num);
pin->cfg.initial_value = 0;
pin->cfg.initial_value = init_value;
pin->cfg.mode = init_mode;
pin->cfg.pull = init_pull;
@ -74,17 +80,106 @@ static mrb_value mrb_gpio_initialize(mrb_state *mrb, mrb_value self) {
}
static mrb_value mrb_gpio_on(mrb_state *mrb, mrb_value self) {
mrb_gpio_t *pin = mrb_data_get_ptr(mrb, self, &mrb_gpio_type);
if (pin == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized GPIO struct");
}
mrb_machine_gpio_impl_write(pin->pin, MACHINE_GPIO_HIGH);
return mrb_nil_value();
}
static mrb_value mrb_gpio_off(mrb_state *mrb, mrb_value self) {
mrb_gpio_t *pin = mrb_data_get_ptr(mrb, self, &mrb_gpio_type);
if (pin == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized GPIO struct");
}
mrb_machine_gpio_impl_write(pin->pin, MACHINE_GPIO_LOW);
return mrb_nil_value();
}
static mrb_value mrb_gpio_toggle(mrb_state *mrb, mrb_value self) {
mrb_gpio_t *pin = mrb_data_get_ptr(mrb, self, &mrb_gpio_type);
if (pin == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized GPIO struct");
}
mrb_machine_gpio_impl_toggle(pin->pin);
return mrb_nil_value();
}
static mrb_value mrb_gpio_get_value(mrb_state *mrb, mrb_value self) {
mrb_gpio_t *pin = mrb_data_get_ptr(mrb, self, &mrb_gpio_type);
if (pin == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized GPIO struct");
}
int val = mrb_machine_gpio_impl_read(pin->pin);
return mrb_int_value(mrb, val);
}
static mrb_value mrb_gpio_set_value(mrb_state *mrb, mrb_value self) {
mrb_gpio_t *pin = mrb_data_get_ptr(mrb, self, &mrb_gpio_type);
if (pin == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized GPIO struct");
}
mrb_value new_value = mrb_get_arg1(mrb);
mrb_ensure_integer_type(mrb, new_value);
mrb_machine_gpio_impl_write(pin->pin, mrb_integer(new_value));
return mrb_nil_value();
}
static mrb_value mrb_gpio_config(mrb_state *mrb, mrb_value self) {
mrb_value new_cfg = mrb_get_arg1(mrb);
mrb_gpio_t *pin = mrb_data_get_ptr(mrb, self, &mrb_gpio_type);
if (pin == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "Uninitialized GPIO struct");
}
machine_gpio_mode_t new_mode = pin->cfg.mode;
machine_gpio_pull_t new_pull = pin->cfg.pull;
/* Optional parameters, do not change if not received from hash */
mrb_value pin_mode = mrb_hash_get(mrb, new_cfg, mrb_symbol_value(mrb_intern_static(mrb, "mode", 4)));
if (!mrb_nil_p(pin_mode)) {
mrb_ensure_integer_type(mrb, pin_mode);
new_mode = mrb_integer(pin_mode);
if (new_mode >= MACHINE_GPIO_MODE_END) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "Invalid GPIO mode");
}
}
mrb_value pin_pull = mrb_hash_get(mrb, new_cfg, mrb_symbol_value(mrb_intern_static(mrb, "pull", 4)));
if (!mrb_nil_p(pin_pull)) {
mrb_ensure_integer_type(mrb, pin_pull);
new_pull = mrb_integer(pin_pull);
if (new_pull >= MACHINE_GPIO_PULL_END) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "Invalid GPIO pull");
}
}
pin->cfg.mode = new_mode;
pin->cfg.pull = new_pull;
mrb_machine_gpio_impl_config(pin->pin, &pin->cfg);
return mrb_nil_value();
}
void mrb_machine_gpio_gem_init(mrb_state *mrb) {
/**
* Example:
* pin_led = Machine::GPIO.new({pin: 10, mode: Machine::GPIO::OUTPUT_OD, pull: Machine::GPIO::PULLUP })
* pin_led = led = Machine::GPIO.new({
* pin: 10,
* mode: Machine::GPIO::OUTPUT_OD,
* pull: Machine::GPIO::PULL_NONE,
* init: Machine::GPIO::ON
* })
* pin_btn = Machine::GPIO.new({pin: 2}) # Default mode is Machine::GPIO::INPUT
* pin_led.on # Set to logical high
* pin_led.off # Set to logical low
@ -94,6 +189,8 @@ void mrb_machine_gpio_gem_init(mrb_state *mrb) {
struct RClass *module_machine = mrb_define_module(mrb, "Machine");
struct RClass *class_gpio = mrb_define_class_under(mrb, module_machine, "GPIO", mrb->object_class);
MRB_SET_INSTANCE_TT(class_gpio, MRB_TT_CDATA);
/* Machine::GPIO::OFF / Machine::GPIO::ON */
mrb_define_const(mrb, class_gpio, "OFF", mrb_fixnum_value(MACHINE_GPIO_LOW));
mrb_define_const(mrb, class_gpio, "ON", mrb_fixnum_value(MACHINE_GPIO_HIGH));
@ -104,13 +201,18 @@ void mrb_machine_gpio_gem_init(mrb_state *mrb) {
mrb_define_const(mrb, class_gpio, "PULL_DOWN", mrb_fixnum_value(MACHINE_GPIO_PULL_DOWN));
/* Machine::GPIO::MODE_INPUT / Machine::GPIO::MODE_OUTPUT_PP / Machine::GPIO::MODE_OUTPUT_OD */
mrb_define_const(mrb, class_gpio, "MODE_INPUT", mrb_fixnum_value(MACHINE_GPIO_MODE_INPUT));
mrb_define_const(mrb, class_gpio, "MODE_OUTPUT_PP", mrb_fixnum_value(MACHINE_GPIO_MODE_OUTPUT_PUSHPULL));
mrb_define_const(mrb, class_gpio, "MODE_OUTPUT_OD", mrb_fixnum_value(MACHINE_GPIO_MODE_OUTPUT_OPENDRAIN));
mrb_define_const(mrb, class_gpio, "INPUT", mrb_fixnum_value(MACHINE_GPIO_MODE_INPUT));
mrb_define_const(mrb, class_gpio, "OUTPUT_PP", mrb_fixnum_value(MACHINE_GPIO_MODE_OUTPUT_PUSHPULL));
mrb_define_const(mrb, class_gpio, "OUTPUT_OD", mrb_fixnum_value(MACHINE_GPIO_MODE_OUTPUT_OPENDRAIN));
/* Instance methods */
mrb_define_method(mrb, class_gpio, "initialize", mrb_gpio_initialize, MRB_ARGS_ARG(1, 0));
mrb_define_method(mrb, class_gpio, "on", mrb_gpio_on, MRB_ARGS_NONE());
mrb_define_method(mrb, class_gpio, "off", mrb_gpio_off, MRB_ARGS_NONE());
mrb_define_method(mrb, class_gpio, "toggle", mrb_gpio_toggle, MRB_ARGS_NONE());
mrb_define_method(mrb, class_gpio, "value", mrb_gpio_get_value, MRB_ARGS_NONE());
mrb_define_method(mrb, class_gpio, "value=", mrb_gpio_set_value, MRB_ARGS_ARG(1, 0));
mrb_define_method(mrb, class_gpio, "config", mrb_gpio_config, MRB_ARGS_ARG(1, 0));
}
void mrb_machine_gpio_gem_final(mrb_state *mrb) {

View File

@ -31,5 +31,8 @@ typedef struct {
} machine_gpio_config_t;
int mrb_machine_gpio_impl_config(uint32_t pin, machine_gpio_config_t *cfg);
int mrb_machine_gpio_impl_read(uint32_t pin);
int mrb_machine_gpio_impl_write(uint32_t pin, machine_gpio_value_t value);
int mrb_machine_gpio_impl_toggle(uint32_t pin);
#endif // MRBGEMS_MACHINE_GPIO_GPIO_H