diff --git a/src/blink/Makefile b/src/blink/Makefile new file mode 100644 index 0000000..d50b5ff --- /dev/null +++ b/src/blink/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=blink +OBJS=blink.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/blink/blink.c b/src/blink/blink.c new file mode 100644 index 0000000..91951ce --- /dev/null +++ b/src/blink/blink.c @@ -0,0 +1,23 @@ +#include +#include + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOC); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + for (;;) { + gpio_clear(GPIOC, GPIO13); + + for (int i=0; i<1000000; i++) + asm volatile (""); + + gpio_set(GPIOC, GPIO13); + + for (int i=0; i<2000000; i++) + asm volatile (""); + } +} diff --git a/src/blink2/Makefile b/src/blink2/Makefile new file mode 100644 index 0000000..d50b5ff --- /dev/null +++ b/src/blink2/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=blink +OBJS=blink.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/blink2/blink.c b/src/blink2/blink.c new file mode 100644 index 0000000..0e6fccd --- /dev/null +++ b/src/blink2/blink.c @@ -0,0 +1,33 @@ +#include +#include +#include + +static void delay_ms(unsigned int ms) +{ + systick_clear(); + for (unsigned int i=0; i +#include +#include + +static void delay_ms(unsigned int ms) +{ + systick_clear(); + for (unsigned int i=0; i +#include + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOC); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + // PA0 ... PA2 = LEDs + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO0); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO1); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO2); + + // PA3 = button (pull-up) + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO3); + gpio_set(GPIOA, GPIO3); + + for (;;) { + if (gpio_get(GPIOA, GPIO3)) + gpio_set(GPIOA, GPIO0 | GPIO1 | GPIO2); + else + gpio_clear(GPIOA, GPIO0 | GPIO1 | GPIO2); + } + + return 0; +} diff --git a/src/example.mk b/src/example.mk new file mode 100644 index 0000000..7fca689 --- /dev/null +++ b/src/example.mk @@ -0,0 +1,8 @@ +STM32LIB=$(ROOT)/../ucw-stm32lib +OPENCM3_DIR=$(ROOT)/../libopencm3 + +WITH_BOOT_LOADER=1 +WITH_DFU_FLASH=1 +DFU_ARGS=-d 4242:0008 + +include $(STM32LIB)/mk/bluepill.mk diff --git a/src/matrix/Makefile b/src/matrix/Makefile new file mode 100644 index 0000000..45766e2 --- /dev/null +++ b/src/matrix/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=matrix +OBJS=matrix.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/matrix/matrix.c b/src/matrix/matrix.c new file mode 100644 index 0000000..947c915 --- /dev/null +++ b/src/matrix/matrix.c @@ -0,0 +1,167 @@ +#include +#include + +#include + +typedef unsigned char byte; + +static void wait(void) +{ + for (int i=0; i<7200; i++) + asm volatile (""); +} + +static void set_reg(int reg, int data) +{ + data |= reg << 8; + + gpio_clear(GPIOB, GPIO13); + wait(); + + for (int mask=0x8000; mask; mask >>= 1) { + if (data & mask) + gpio_set(GPIOB, GPIO12); + else + gpio_clear(GPIOB, GPIO12); + wait(); + gpio_set(GPIOB, GPIO14); + wait(); + gpio_clear(GPIOB, GPIO14); + wait(); + } + + gpio_set(GPIOB, GPIO13); + wait(); +} + +byte display[8]; + +#if 0 +static unsigned char smile[8] = { + 0x66, /* .##..##. */ + 0x66, /* .##..##. */ + 0x00, /* ........ */ + 0x18, /* ...##... */ + 0x00, /* ........ */ + 0xc3, /* ##....## */ + 0x66, /* .##..##. */ + 0x3c, /* ..####.. */ +}; +#endif + +static void refresh_display(void) +{ + for (int i=1; i<=8; i++) + set_reg(i, display[8-i]); +} + +static signed char dirs[4][2] = {{1,0}, {0,-1}, {-1,0}, {0,1}}; + +static byte snake_dir; +#define SNAKE_MAX 65 +static byte snake[SNAKE_MAX][2]; +static byte snake_tail, snake_head; +static byte food[2]; +static unsigned int rng_state = 0xdeadbeef; + +static byte buttons[2]; + +static void gen_food(void) +{ + food[0] = (rng_state >> 28) & 7; + food[1] = (rng_state >> 20) & 7; + rng_state *= 0x3771cadb; +} + +static void snake_init(void) +{ + snake[0][0] = 0; + snake[0][1] = 0; + snake_dir = 3; + snake_tail = 0; + snake_head = 1; + gen_food(); +} + +static void snake_show(void) +{ + memset(display, 0, 8); + for (int i=snake_tail; i != snake_head; i = (i+1) % SNAKE_MAX) + display[snake[i][0]] |= 1 << snake[i][1]; + display[food[0]] |= 1 << food[1]; + refresh_display(); +} + +static void snake_step(void) +{ + if (buttons[0]) + snake_dir = (snake_dir+3) % 4; + else if (buttons[1]) + snake_dir = (snake_dir+1) % 4; + + int hi = (snake_head + SNAKE_MAX - 1) % SNAKE_MAX; + int x = snake[hi][0] + dirs[snake_dir][0]; + int y = snake[hi][1] + dirs[snake_dir][1]; + + if (x < 0 || x > 7 || y < 0 || y > 7) + return; + + snake[snake_head][0] = x; + snake[snake_head][1] = y; + snake_head = (snake_head + 1) % SNAKE_MAX; + + if (x == food[0] && y == food[1]) + gen_food(); + else + snake_tail = (snake_tail + 1) % SNAKE_MAX; + + snake_show(); +} + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + // PB12 = display DIN + // PB13 = display CS* + // PB14 = display CLK + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12 | GPIO13 | GPIO14); + gpio_clear(GPIOB, GPIO12); + gpio_set(GPIOB, GPIO13); + gpio_clear(GPIOB, GPIO14); + + // PA0 = left button + // PA1 = right button + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0 | GPIO1); + gpio_set(GPIOA, GPIO0 | GPIO1); + + refresh_display(); + set_reg(9, 0); + set_reg(10, 0); // intensity + set_reg(11, 7); + set_reg(13, 0); // test + set_reg(12, 1); // shutdown + + snake_init(); + snake_show(); + + for (;;) { + buttons[0] = buttons[1] = 0; + for (int i=0; i<1000000; i++) { + if (!gpio_get(GPIOA, GPIO0)) + buttons[0] = 1; + if (!gpio_get(GPIOA, GPIO1)) + buttons[1] = 1; + asm volatile (""); + } + + gpio_toggle(GPIOC, GPIO13); + snake_step(); + } +} diff --git a/src/timer1-clock/Makefile b/src/timer1-clock/Makefile new file mode 100644 index 0000000..590ac44 --- /dev/null +++ b/src/timer1-clock/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=timer +OBJS=timer.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/timer1-clock/timer.c b/src/timer1-clock/timer.c new file mode 100644 index 0000000..2a7d732 --- /dev/null +++ b/src/timer1-clock/timer.c @@ -0,0 +1,34 @@ +#include +#include +#include + +static void delay_ms(unsigned int ms) +{ + timer_set_period(TIM3, 2*ms); + timer_enable_counter(TIM3); + while (TIM_CR1(TIM3) & TIM_CR1_CEN) + ; +} + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_TIM3); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + timer_set_prescaler(TIM3, 35999); // 72 MHz / 36000 = 2 kHz + timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_DOWN); + timer_one_shot_mode(TIM3); + + for (;;) { + gpio_clear(GPIOC, GPIO13); + delay_ms(100); + gpio_set(GPIOC, GPIO13); + delay_ms(500); + } + + return 0; +} diff --git a/src/timer2-irq/Makefile b/src/timer2-irq/Makefile new file mode 100644 index 0000000..590ac44 --- /dev/null +++ b/src/timer2-irq/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=timer +OBJS=timer.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/timer2-irq/timer.c b/src/timer2-irq/timer.c new file mode 100644 index 0000000..045aa47 --- /dev/null +++ b/src/timer2-irq/timer.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +void tim3_isr(void) +{ + if (TIM_SR(TIM3) & TIM_SR_UIF) { + TIM_SR(TIM3) &= ~TIM_SR_UIF; + gpio_toggle(GPIOC, GPIO13); + } +} + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_TIM3); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + timer_set_prescaler(TIM3, 35999); // 72 MHz / 36000 = 2 kHz + timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_period(TIM3, 199); // 200 ticks = 100 ms + timer_update_on_overflow(TIM3); + timer_enable_irq(TIM3, TIM_DIER_UIE); + nvic_enable_irq(NVIC_TIM3_IRQ); + timer_enable_counter(TIM3); + + for (;;) { + asm volatile ("wfi"); + } + + return 0; +} diff --git a/src/timer3-oc/Makefile b/src/timer3-oc/Makefile new file mode 100644 index 0000000..590ac44 --- /dev/null +++ b/src/timer3-oc/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=timer +OBJS=timer.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/timer3-oc/timer.c b/src/timer3-oc/timer.c new file mode 100644 index 0000000..92ddee1 --- /dev/null +++ b/src/timer3-oc/timer.c @@ -0,0 +1,37 @@ +#include +#include +#include + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_TIM3); + rcc_periph_reset_pulse(RST_TIM3); // XXX + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOC, GPIO13); + + // PB0 = TIM3_CH3 + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO0); + + timer_set_prescaler(TIM3, 35999); // 72 MHz / 36000 = 2 kHz + timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_period(TIM3, 1999); + timer_update_on_overflow(TIM3); + + timer_set_oc_mode(TIM3, TIM_OC3, TIM_OCM_PWM1); + timer_set_oc_value(TIM3, TIM_OC3, 500); + timer_set_oc_polarity_high(TIM3, TIM_OC3); + timer_enable_oc_output(TIM3, TIM_OC3); + + timer_enable_counter(TIM3); + + for (;;) { + asm volatile ("wfi"); + } + + return 0; +} diff --git a/src/timer4-pwm/Makefile b/src/timer4-pwm/Makefile new file mode 100644 index 0000000..590ac44 --- /dev/null +++ b/src/timer4-pwm/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=timer +OBJS=timer.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/timer4-pwm/timer.c b/src/timer4-pwm/timer.c new file mode 100644 index 0000000..1a06fc7 --- /dev/null +++ b/src/timer4-pwm/timer.c @@ -0,0 +1,37 @@ +#include +#include +#include + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_TIM3); + rcc_periph_reset_pulse(RST_TIM3); // XXX + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOC, GPIO13); + + // PB0 = TIM3_CH3 + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO0); + + timer_set_prescaler(TIM3, 1); // 72 MHz / 2 = 36 MHz + timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_period(TIM3, 999); // 36 MHz / 1000 = 36 kHz + timer_update_on_overflow(TIM3); + + timer_set_oc_mode(TIM3, TIM_OC3, TIM_OCM_PWM1); + timer_set_oc_value(TIM3, TIM_OC3, 150); + timer_set_oc_polarity_high(TIM3, TIM_OC3); + timer_enable_oc_output(TIM3, TIM_OC3); + + timer_enable_counter(TIM3); + + for (;;) { + asm volatile ("wfi"); + } + + return 0; +} diff --git a/src/timer5-pwm/Makefile b/src/timer5-pwm/Makefile new file mode 100644 index 0000000..590ac44 --- /dev/null +++ b/src/timer5-pwm/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=timer +OBJS=timer.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/timer5-pwm/timer.c b/src/timer5-pwm/timer.c new file mode 100644 index 0000000..9ff0f61 --- /dev/null +++ b/src/timer5-pwm/timer.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +int up = 1; +int pwm; + +void tim4_isr(void) +{ + if (TIM_SR(TIM4) & TIM_SR_UIF) { + TIM_SR(TIM4) &= ~TIM_SR_UIF; + if (up) { + pwm += 5; + if (pwm == 1000) { + pwm = 995; + up = 0; + } + } else { + pwm -= 5; + if (pwm < 0) { + pwm = 5; + up = 1; + } + } + timer_set_oc_value(TIM3, TIM_OC3, pwm); + } +} + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_TIM3); + rcc_periph_clock_enable(RCC_TIM4); + rcc_periph_reset_pulse(RST_TIM3); // XXX + rcc_periph_reset_pulse(RST_TIM4); // XXX + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOC, GPIO13); + + // PB0 = TIM3_CH3 + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO0); + + timer_set_prescaler(TIM3, 1); // 72 MHz / 2 = 36 MHz + timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_period(TIM3, 999); // 36 MHz / 1000 = 36 kHz + timer_update_on_overflow(TIM3); + + timer_set_oc_mode(TIM3, TIM_OC3, TIM_OCM_PWM1); + timer_set_oc_value(TIM3, TIM_OC3, 50); + timer_set_oc_polarity_high(TIM3, TIM_OC3); + timer_enable_oc_output(TIM3, TIM_OC3); + + timer_enable_counter(TIM3); + + timer_set_prescaler(TIM4, 35999); // 72 MHz / 36000 = 2 kHz + timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_period(TIM4, 2); // 2 kHz / 2 = 1 kHz + timer_update_on_overflow(TIM4); + timer_enable_irq(TIM4, TIM_DIER_UIE); + nvic_enable_irq(NVIC_TIM4_IRQ); + timer_enable_counter(TIM4); + + for (;;) { + asm volatile ("wfi"); + } + + return 0; +} diff --git a/src/usart1/Makefile b/src/usart1/Makefile new file mode 100644 index 0000000..7a2e50f --- /dev/null +++ b/src/usart1/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=usart +OBJS=usart.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/usart1/usart.c b/src/usart1/usart.c new file mode 100644 index 0000000..d6fc48e --- /dev/null +++ b/src/usart1/usart.c @@ -0,0 +1,38 @@ +#include +#include +#include + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_USART1); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + // PA10 = RX1, PA9 = TX1 + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO10); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9); + + usart_set_baudrate(USART1, 115200); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_mode(USART1, USART_MODE_TX_RX); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + usart_enable(USART1); + + int c = 32; + for (;;) { + gpio_toggle(GPIOC, GPIO13); + + usart_send(USART1, c); + usart_wait_send_ready(USART1); + + c++; + if (c == 127) + c = 32; + } +} diff --git a/src/usart2/Makefile b/src/usart2/Makefile new file mode 100644 index 0000000..7a2e50f --- /dev/null +++ b/src/usart2/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=usart +OBJS=usart.o +LIB_OBJS= + +include $(ROOT)/example.mk diff --git a/src/usart2/usart.c b/src/usart2/usart.c new file mode 100644 index 0000000..4524767 --- /dev/null +++ b/src/usart2/usart.c @@ -0,0 +1,36 @@ +#include +#include +#include + +int main(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_USART1); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + + // PA10 = RX1, PA9 = TX1 + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO10); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9); + + usart_set_baudrate(USART1, 115200); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_mode(USART1, USART_MODE_TX_RX); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + usart_enable(USART1); + + for (;;) { + gpio_toggle(GPIOC, GPIO13); + + usart_wait_recv_ready(USART1); + int c = usart_recv(USART1); + + usart_send(USART1, c); + usart_wait_send_ready(USART1); + } +}