From 5533dc807f09426143ef5e430a35b8494744e2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Mon, 20 Jun 2022 21:33:27 +0200 Subject: [PATCH] [beken-72xx] Implement Wiring core, digital I/O and PWM --- README.md | 2 +- arduino/beken-72xx/cores/arduino/wiring.c | 14 +++- .../beken-72xx/cores/arduino/wiring_analog.c | 70 +++++++++++++++++++ .../beken-72xx/cores/arduino/wiring_digital.c | 62 ++++++++++++++++ 4 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 arduino/beken-72xx/cores/arduino/wiring_analog.c create mode 100644 arduino/beken-72xx/cores/arduino/wiring_digital.c diff --git a/README.md b/README.md index 15a2516..b15679a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Note: this list will probably change with each functionality update.   | `realtek-ambz` | `beken-72xx` --------------------|----------------|------------- Core functions | ✔️ | ✔️ -GPIO/PWM/IRQ | ✔️/✔️/✔️ | ❌/❌/❌ +GPIO/PWM/IRQ | ✔️/✔️/✔️ | ❓/✔️/❌ Analog input | ✔️ | ❌ UART I/O | ✔️ | ❌ Flash I/O | ✔️ | ✔️ diff --git a/arduino/beken-72xx/cores/arduino/wiring.c b/arduino/beken-72xx/cores/arduino/wiring.c index a5f590f..4ac8103 100644 --- a/arduino/beken-72xx/cores/arduino/wiring.c +++ b/arduino/beken-72xx/cores/arduino/wiring.c @@ -8,12 +8,24 @@ void delayMilliseconds(unsigned long ms) { rtos_delay_milliseconds(ms); } -void delayMicroseconds(unsigned int us) {} +void delayMicroseconds(unsigned int us) { + // TODO implement this properly + us /= 10; + volatile uint32_t i, j; + for (i = 0; i < us; i++) { + for (j = 0; j < 100; j++) {} + } +} uint32_t millis() { return xTaskGetTickCount() * portTICK_PERIOD_MS; } +uint32_t micros() { + // TODO implement this properly + return millis() * 1000; +} + void yield() { vTaskDelay(1); taskYIELD(); diff --git a/arduino/beken-72xx/cores/arduino/wiring_analog.c b/arduino/beken-72xx/cores/arduino/wiring_analog.c new file mode 100644 index 0000000..816b3c1 --- /dev/null +++ b/arduino/beken-72xx/cores/arduino/wiring_analog.c @@ -0,0 +1,70 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */ + +#include +#include + +static GPIO_INDEX pwmToGpio[] = { + GPIO6, // PWM0 + GPIO7, // PWM1 + GPIO8, // PWM2 + GPIO9, // PWM3 + GPIO24, // PWM4 + GPIO26, // PWM5 +}; + +static uint8_t gpioToPwm(GPIO_INDEX gpio) { + for (uint8_t i = 0; i < sizeof(pwmToGpio); i++) { + if (pwmToGpio[i] == gpio) + return i; + } + return 0; +} + +static pwm_param_t pwm; + +uint16_t analogReadVoltage(pin_size_t pinNumber) { + // TODO + return 0; +} + +uint16_t analogReadMaxVoltage(pin_size_t pinNumber) { + return 3300; +} + +void analogWrite(pin_size_t pinNumber, int value) { + PinInfo *pin = pinInfo(pinNumber); + if (!pin) + return; + if (!pinSupported(pin, PIN_PWM)) + return; + + float percent = value * 1.0 / (1 << _analogWriteResolution); + uint32_t dutyCycle = percent * _analogWritePeriod * 26 - 1; + pwm.channel = gpioToPwm(pin->gpio); + pwm.duty_cycle = dutyCycle; + + if (!pinEnabled(pin, PIN_PWM)) { + // enable PWM and set its value + pwm.cfg.bits.en = PWM_ENABLE; + pwm.cfg.bits.int_en = PWM_INT_DIS; + pwm.cfg.bits.mode = PWM_PWM_MODE; + pwm.cfg.bits.clk = PWM_CLK_26M; + pwm.end_value = 26 * _analogWritePeriod - 1; + pwm.p_Int_Handler = NULL; + __wrap_bk_printf_disable(); + sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, &pwm); + __wrap_bk_printf_enable(); + pin->enabled &= ~PIN_GPIO; + pin->enabled |= PIN_PWM; + } else if (value == 0) { + // disable PWM + pwm.cfg.bits.en = PWM_DISABLE; + __wrap_bk_printf_disable(); + sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, &pwm); + __wrap_bk_printf_enable(); + pin->enabled &= ~PIN_PWM; + } else { + // update duty cycle + sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm); + } +} diff --git a/arduino/beken-72xx/cores/arduino/wiring_digital.c b/arduino/beken-72xx/cores/arduino/wiring_digital.c new file mode 100644 index 0000000..d1c0acc --- /dev/null +++ b/arduino/beken-72xx/cores/arduino/wiring_digital.c @@ -0,0 +1,62 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */ + +#include + +void pinMode(pin_size_t pinNumber, PinMode pinMode) { + PinInfo *pin = pinInfo(pinNumber); + if (!pin) + return; + if (!pinSupported(pin, PIN_GPIO)) + return; + if (pinEnabled(pin, PIN_PWM)) + // disable PWM before using the pin + analogWrite(pinNumber, 0); + if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode) + return; + switch (pinMode) { + case INPUT: + gpio_config(pin->gpio, GMODE_INPUT); + break; + case OUTPUT: + gpio_config(pin->gpio, GMODE_OUTPUT); + break; + case INPUT_PULLUP: + gpio_config(pin->gpio, GMODE_INPUT_PULLUP); + break; + case INPUT_PULLDOWN: + gpio_config(pin->gpio, GMODE_INPUT_PULLDOWN); + break; + case OUTPUT_OPENDRAIN: + gpio_config(pin->gpio, GMODE_SET_HIGH_IMPENDANCE); + break; + } + pin->enabled |= PIN_GPIO; + pin->mode = pinMode; +} + +void digitalWrite(pin_size_t pinNumber, PinStatus status) { + // verify level is 0 or 1 + if (status > HIGH) + return; + PinInfo *pin = pinInfo(pinNumber); + if (!pin) + return; + // pin is not GPIO yet or not OUTPUT; enable or disable input pullup + if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin)) { + pinMode(pinNumber, status * INPUT_PULLUP); + return; + } + // write the new state + gpio_output(pin->gpio, status); +} + +PinStatus digitalRead(pin_size_t pinNumber) { + PinInfo *pin = pinInfo(pinNumber); + if (!pin) + return 0; + // pin is not GPIO yet or not INPUT; change the mode + if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin)) + pinMode(pinNumber, INPUT); + // read the value + return gpio_input(pin->gpio); +}