diff --git a/examples/GPIO/GPIO.c b/examples/GPIO/GPIO.c new file mode 100644 index 0000000000000000000000000000000000000000..ed430880241ba0eb164677bf5c2a07d2dd197917 --- /dev/null +++ b/examples/GPIO/GPIO.c @@ -0,0 +1,47 @@ +// blink, but with arduino-like HAL +// Could be defined here, or in the processor defines. +#define SYSTEM_CORE_CLOCK 48000000 + +#include "ch32v003fun.h" +#include "wiring_digital.h" +#include <stdio.h> + +#define APB_CLOCK SYSTEM_CORE_CLOCK + +uint32_t count; + +int main() { + SystemInit48HSI(); + + // Enable GPIO ports + enablePort(port_C); + enablePort(port_D); + + for (int i = pin_C0; i <= pin_C7; i++) { + pinMode(i, pinMode_O_pushPull); + } + + // GPIO D4 Push-Pull + pinMode(pin_D4, pinMode_O_pushPull); + + while (1) { + // Turn on pins + digitalWrite(pin_C0, high); + digitalWrite(pin_D4, high); + Delay_Ms(250); + // Turn off pins + digitalWrite(pin_C0, low); + digitalWrite(pin_D4, low); + Delay_Ms(250); + for (int i = pin_C0; i <= pin_C7; i++) { + digitalWrite(i, high); + Delay_Ms(50); + } + for (int i = pin_C7; i >= pin_C0; i--) { + digitalWrite(i, low); + Delay_Ms(50); + } + Delay_Ms(250); + count++; + } +} diff --git a/examples/GPIO/Makefile b/examples/GPIO/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5090155f3f5f8a616ff580b733b6ef8b512906a4 --- /dev/null +++ b/examples/GPIO/Makefile @@ -0,0 +1,43 @@ +TARGET:=GPIO + +all : flash + +PREFIX:=riscv64-unknown-elf + +GPIO_Toggle:=EXAM/GPIO/GPIO_Toggle/User + +EVT:=../../ch32v003evt + +MINICHLINK:=../../minichlink +CH32V003FUN:=../../ch32v003fun + +CFLAGS:= \ + -g -Os -flto -ffunction-sections \ + -static-libgcc \ + -march=rv32ec \ + -mabi=ilp32e \ + -I/usr/include/newlib \ + -I$(CH32V003FUN) \ + -nostdlib \ + -I. -DTINYVECTOR -Wall + +LDFLAGS:=-T $(CH32V003FUN)/ch32v003fun.ld -Wl,--gc-sections -L../../misc -lgcc + +SYSTEM_C:=$(CH32V003FUN)/ch32v003fun.c + +$(TARGET).elf : $(SYSTEM_C) $(TARGET).c wiring_digital.c + $(PREFIX)-gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) + +$(TARGET).bin : $(TARGET).elf + $(PREFIX)-size $^ + $(PREFIX)-objdump -S $^ > $(TARGET).lst + $(PREFIX)-objdump -t $^ > $(TARGET).map + $(PREFIX)-objcopy -O binary $< $(TARGET).bin + $(PREFIX)-objcopy -O ihex $< $(TARGET).hex + +flash : $(TARGET).bin + $(MINICHLINK)/minichlink -w $< flash -b + +clean : + rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex + diff --git a/examples/GPIO/README.md b/examples/GPIO/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a6c23799ff7e6df932b10774273f86094daac8b3 --- /dev/null +++ b/examples/GPIO/README.md @@ -0,0 +1,14 @@ +# GPIO Libaray +On the shoulders of the Blink example, this Arduino-like GPIO library stands. + +All pins are adressable as outputs, inputs, with pull-up, etc. +The pins are in an enum, so you can call them by their name and iterate over them. + +It's your responsibility to not blow up a pin. +Only use one pin for one thing and you should be fine. + +# GPIO Example +Connect LED + 1k resistor to each pin (C0 to C7 and D4) and GND. +Marvel at the colorful glory. + +https://user-images.githubusercontent.com/104343143/231585338-725f1197-dfa0-484d-8707-f0824af80b7e.mp4 diff --git a/examples/GPIO/wiring_digital.c b/examples/GPIO/wiring_digital.c new file mode 100644 index 0000000000000000000000000000000000000000..891441786b5890f97875bc253d39456c64903d99 --- /dev/null +++ b/examples/GPIO/wiring_digital.c @@ -0,0 +1,161 @@ +//#include <stdio.h> + +#include "wiring_digital.h" +#include <stdint.h> + + + +enum GPIOports getPort (enum GPIOpins pin) { + if (pin <= pin_A2) { + return port_A; + } + else if (pin <= pin_C7) { + return port_C; + } + else if (pin <= pin_D7) { + return port_D; + } + return port_none; +} + + + +void enablePort(enum GPIOports port) { + // Enable GPIOs + switch (port) { + case port_A: + RCC->APB2PCENR |= RCC_APB2Periph_GPIOA; + break; + case port_C: + RCC->APB2PCENR |= RCC_APB2Periph_GPIOC; + break; + case port_D: + RCC->APB2PCENR |= RCC_APB2Periph_GPIOD; + break; + case port_none: + break; + } +} + + + +void pinMode(enum GPIOpins pin, enum GPIOpinMode mode) { + GPIO_TypeDef * GPIOx; + uint16_t PinOffset = 4; + + if (pin <= pin_A2) { + GPIOx = GPIOA; + PinOffset *= pin; + } + else if (pin <= pin_C7) { + GPIOx = GPIOC; + PinOffset *= (pin - 2); + } + else if (pin <= pin_D7) { + GPIOx = GPIOD; + PinOffset *= (pin - 10); + } + else { + return; + } + + GPIOx->CFGLR &= ~(0b1111<<PinOffset); // zero the 4 configuration bits + + uint8_t target_pin_state = pinState_nochange; // by default, pin shall retain its state + + uint8_t modeMask = 0; // configuration mask + + switch (mode) { + case pinMode_I_floating: + modeMask = GPIO_CNF_IN_FLOATING; + break; + case pinMode_I_pullUp: + modeMask = GPIO_CNF_IN_PUPD; + target_pin_state = pinState_high; + break; + case pinMode_I_pullDown: + modeMask = GPIO_CNF_IN_PUPD; + target_pin_state = pinState_low; + break; + case pinMode_I_analog: + modeMask = GPIO_CNF_IN_ANALOG; + break; + case pinMode_O_pushPull: + modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_PP; + break; + case pinMode_O_openDrain: + modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_OD; + break; + case pinMode_O_pushPullMux: + modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF; + break; + case pinMode_O_openDrainMux: + modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF; + break; + } + + // wirte mask to CFGR + GPIOx->CFGLR |= modeMask<<PinOffset; + + // set pin state + if (target_pin_state > pinState_nochange) { + digitalWrite(pin, target_pin_state - 1); + } +} + + + +void digitalWrite(enum GPIOpins pin, uint8_t value) { + // no checks given whether pin is currently being toggled by timer! your output trannys are in your hands! beware the magic smoke! + GPIO_TypeDef * GPIOx; + uint16_t PinOffset = 0; + + if (pin <= pin_A2) { + GPIOx = GPIOA; + PinOffset = pin; + } + else if (pin <= pin_C7) { + GPIOx = GPIOC; + PinOffset = (pin - 2); + } + else if (pin <= pin_D7) { + GPIOx = GPIOD; + PinOffset = (pin - 10); + } + else { + return; + } + + if (value) { + GPIOx-> BSHR |= 1 << PinOffset; + } + else { + GPIOx-> BSHR |= 1 << (16 + PinOffset); + } +} + + + +uint8_t digitalRead(uint8_t pin) { + GPIO_TypeDef * GPIOx; + uint16_t PinOffset = 0; + + if (pin <= pin_A2) { + GPIOx = GPIOA; + PinOffset = pin; + } + else if (pin <= pin_C7) { + GPIOx = GPIOC; + PinOffset = (pin - 2); + } + else if (pin <= pin_D7) { + GPIOx = GPIOD; + PinOffset = (pin - 10); + } + else { + return 0; + } + + int8_t result = (GPIOx->INDR >> PinOffset) & 1; + return result; +} diff --git a/examples/GPIO/wiring_digital.h b/examples/GPIO/wiring_digital.h new file mode 100644 index 0000000000000000000000000000000000000000..8b7deeec0e3d32d46966540e3699cb02d91f15d2 --- /dev/null +++ b/examples/GPIO/wiring_digital.h @@ -0,0 +1,73 @@ +#ifndef WIRING_DIGITAL_H +#define WIRING_DIGITAL_H + +#include "../../ch32v003fun/ch32v003fun.h" + +// Define the pins that will be used for GPIO +#define MY_GPIO_PIN_1 1 +#define MY_GPIO_PIN_2 2 +// Add more pins as needed + + + +enum lowhigh { + low, + high, +}; + + + +enum GPIOports{ + port_A, + port_C, + port_D, + port_none, +}; + +enum GPIOpins{ + pin_A1, + pin_A2, + pin_C0, + pin_C1, + pin_C2, + pin_C3, + pin_C4, + pin_C5, + pin_C6, + pin_C7, + pin_D0, + pin_D1, + pin_D2, + pin_D3, + pin_D4, + pin_D5, + pin_D6, + pin_D7, + pin_none, +}; + +enum GPIOpinMode { + pinMode_I_floating, + pinMode_I_pullUp, //pull-mode + ODR(1) + pinMode_I_pullDown, //pull-mode + ODR(0) + pinMode_I_analog, + pinMode_O_pushPull, + pinMode_O_openDrain, + pinMode_O_pushPullMux, + pinMode_O_openDrainMux, +}; + +enum GPIOpinState { + pinState_nochange, + pinState_low, + pinState_high, +}; + +enum GPIOports getPort (enum GPIOpins pin); + +void enablePort(enum GPIOports port); +void pinMode(enum GPIOpins pin, enum GPIOpinMode mode); +void digitalWrite(enum GPIOpins pin, uint8_t value); +uint8_t digitalRead(uint8_t pin); + +#endif // WIRING_DIGITAL_H