mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
PWM LED driving
Change-Id: Ic3eb3c13e5a0f35e13caf96039304647b2363bd2
This commit is contained in:
20
ion/include/ion/led.h
Normal file
20
ion/include/ion/led.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef ION_LED_H
|
||||
#define ION_LED_H
|
||||
|
||||
/* ION abstracts pushing pixels to the screen.
|
||||
*
|
||||
* There could be a single entry point, set_pixel, but setting pixels one by one
|
||||
* incurs quite a large overhead because you need to send the coordinate of each
|
||||
* pixel to the screen.
|
||||
*
|
||||
* Many displays support sending contiguous pixels without having to repeat the
|
||||
* pixel coordinates every time. We're therefore leveraging this capability
|
||||
* which results in a very consequent speedup (up to ~10x faster). */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint16_t ion_color_t;
|
||||
|
||||
void ion_led_set_color(ion_color_t color);
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
include ion/src/device/boot/Makefile
|
||||
objs += $(addprefix ion/src/device/, init.o heap.o)
|
||||
objs += $(addprefix ion/src/device/, init.o heap.o led.o)
|
||||
objs += $(addprefix ion/src/device/display/,\
|
||||
display.o\
|
||||
gpio.o\
|
||||
|
||||
@@ -19,6 +19,7 @@ void enable_fpu() {
|
||||
void init_platform() {
|
||||
enable_fpu();
|
||||
init_keyboard();
|
||||
ion_led_init();
|
||||
init_display();
|
||||
}
|
||||
|
||||
|
||||
89
ion/src/device/led.c
Normal file
89
ion/src/device/led.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <ion/led.h>
|
||||
#include "registers/registers.h"
|
||||
|
||||
/* Pin used :
|
||||
* PA8 - Red LED - TIM1_CH1
|
||||
* PA9 - Green LED - TIM1_CH2
|
||||
* PA10 - Blue LED -TIM1_CH3
|
||||
*/
|
||||
|
||||
void sleep() {
|
||||
for (volatile int i=0;i<100000; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
void ion_led_gpio_init() {
|
||||
// We are using GPIOA, which live on the AHB1 bus. Let's enable its clock.
|
||||
RCC_AHB1ENR |= GPIOAEN;
|
||||
|
||||
#if 0
|
||||
|
||||
for (int i=8; i<=8; i++) {
|
||||
REGISTER_SET_VALUE(GPIO_MODER(GPIOA), MODER(i), GPIO_MODE_OUTPUT);
|
||||
}
|
||||
char value = 1;
|
||||
while (1) {
|
||||
value = !value;
|
||||
for (int i=8; i<=10; i++) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOA), ODR(i), value);
|
||||
}
|
||||
for (volatile int i=0; i<100000; i++) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
/* RED_LED(PA8), GREEN_LED(PA9), BLUE_LED(PA10) are driven using a timer,
|
||||
* which is an alternate function. */
|
||||
REGISTER_SET_VALUE(GPIO_MODER(GPIOA), MODER(8), GPIO_MODE_ALTERNATE_FUNCTION);
|
||||
REGISTER_SET_VALUE(GPIO_MODER(GPIOA), MODER(9), GPIO_MODE_ALTERNATE_FUNCTION);
|
||||
REGISTER_SET_VALUE(GPIO_MODER(GPIOA), MODER(10), GPIO_MODE_ALTERNATE_FUNCTION);
|
||||
|
||||
/* More precisely, we will use AF01, which maps PA8 to TIM1_CH1, PA9 to
|
||||
* TIM1_CH2 and PA10 to TIM1_CH3. */
|
||||
REGISTER_SET_VALUE(GPIO_AFR(GPIOA, 8), AFR(8), 1);
|
||||
REGISTER_SET_VALUE(GPIO_AFR(GPIOA, 9), AFR(9), 1);
|
||||
REGISTER_SET_VALUE(GPIO_AFR(GPIOA, 10), AFR(10), 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ion_led_timer_init() {
|
||||
/* TIM1 lives on the APB2 bus. Let's enable its clock. */
|
||||
RCC_APB2ENR |= TIM1EN;
|
||||
TIM_PSC(TIM1) = 1000;
|
||||
|
||||
/* Pulse width modulation mode allows you to generate a signal with a
|
||||
* frequency determined by the value of the TIMx_ARR register and a duty cycle
|
||||
* determined by the value of the TIMx_CCRx register. */
|
||||
TIM_ARR(TIM1) = 40000;
|
||||
TIM_CCR1(TIM1) = 20000;
|
||||
TIM_CCR2(TIM1) = 20000;
|
||||
|
||||
|
||||
// Set Channel 1 as output, PWM mode 1
|
||||
REGISTER_SET_VALUE(TIM_CCMR1(TIM1), TIM_OC1M, 6);
|
||||
// Set Channel 2 as output, PWM mode 2
|
||||
REGISTER_SET_VALUE(TIM_CCMR1(TIM1), TIM_OC2M, 6);
|
||||
//REGISTER_SET_VALUE(TIM_CCMR2(TIM1), TIM_OC3M, 6);
|
||||
|
||||
// Output preload enable for channel 1 and 2
|
||||
TIM_CCMR1(TIM1) |= (TIM_OC1PE | TIM_OC2PE);
|
||||
|
||||
// Auto-reload preload enable
|
||||
TIM_CR1(TIM1) |= TIM_ARPE;
|
||||
|
||||
// Enable Capture/Compare channel 1 and channel 2
|
||||
TIM_CCER(TIM1) |= (TIM_CC1E | TIM_CC2E);
|
||||
|
||||
TIM_BDTR(TIM1) |= (TIM_MOE);
|
||||
|
||||
TIM_CR1(TIM1) |= (TIM_CEN); // Enable the counter
|
||||
}
|
||||
|
||||
void ion_led_init() {
|
||||
ion_led_gpio_init();
|
||||
ion_led_timer_init();
|
||||
}
|
||||
|
||||
|
||||
void ion_led_set_color(ion_color_t color) {
|
||||
}
|
||||
@@ -25,4 +25,5 @@
|
||||
#include "spi.h"
|
||||
#include "dma.h"
|
||||
#include "cm4.h"
|
||||
#include "tim.h"
|
||||
//#include "ltdc.h"
|
||||
|
||||
85
ion/src/device/registers/tim.h
Normal file
85
ion/src/device/registers/tim.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef STM32_REGISTERS_TIM_H
|
||||
#define STM32_REGISTERS_TIM_H 1
|
||||
|
||||
#define TIM1_BASE 0x40010000
|
||||
#define TIM2_BASE 0x40000000
|
||||
#define TIM3_BASE 0x40000400
|
||||
#define TIM4_BASE 0x40000800
|
||||
|
||||
#define TIM_REGISTER_AT(timer,offset) (*(volatile uint16_t *)(timer##_BASE+offset))
|
||||
|
||||
// TIM control registers 1
|
||||
|
||||
#define TIM_CR1(timer) TIM_REGISTER_AT(timer, 0x00)
|
||||
|
||||
#define TIM_CEN (1<<0)
|
||||
#define TIM_UDIS (1<<1)
|
||||
#define TIM_URS (1<<2)
|
||||
#define TIM_OPM (1<<3)
|
||||
#define TIM_DIR (1<<4)
|
||||
//#define TIM_CMS
|
||||
#define TIM_ARPE (1<<7)
|
||||
#define TIM_CKD_1 0
|
||||
#define TIM_CKD_2 1
|
||||
#define TIM_CKD_4 2
|
||||
|
||||
// TIM control registers 2
|
||||
|
||||
#define TIM_CR2(timer) TIM_REGISTER_AT(timer, 0x04)
|
||||
|
||||
#define TIM_CDDS (1<<3)
|
||||
#define TIM_MMS_RESET 0
|
||||
#define TIM_MMS_ENABLE 1
|
||||
#define TIM_MMS_UPDATE 2
|
||||
#define TIM_MMS_COMPARE_PULSE 3
|
||||
#define TIM_TI1S (1<<7)
|
||||
|
||||
// TIM capture/compare mode register 1
|
||||
|
||||
#define TIM_CCMR1(timer) TIM_REGISTER_AT(timer, 0x18)
|
||||
|
||||
//#define LOW_BIT_TIM_CC1S 0
|
||||
//#define HIGH_BIT_TIM_CC1S 1
|
||||
#define TIM_OC1PE (1<<3)
|
||||
#define LOW_BIT_TIM_OC1M 4
|
||||
#define HIGH_BIT_TIM_OC1M 6
|
||||
#define TIM_OC2PE (1<<11)
|
||||
#define LOW_BIT_TIM_OC2M 12
|
||||
#define HIGH_BIT_TIM_OC2M 14
|
||||
|
||||
#define TIM_CCMR2(timer) TIM_REGISTER_AT(timer, 0x1C)
|
||||
|
||||
#define LOW_BIT_TIM_OC3M 4
|
||||
#define HIGH_BIT_TIM_OC3M 6
|
||||
|
||||
// TIM capture/compare enable register
|
||||
#define TIM_CCER(timer) TIM_REGISTER_AT(timer, 0x20)
|
||||
|
||||
#define TIM_CC1E (1<<0)
|
||||
#define TIM_CC1P (1<<1)
|
||||
#define TIM_CC1NE (1<<2)
|
||||
#define TIM_CC2E (1<<4)
|
||||
#define TIM_CC2P (1<<5)
|
||||
#define TIM_CC2NE (1<<6)
|
||||
|
||||
#define TIM_CNT(timer) TIM_REGISTER_AT(timer, 0x24)
|
||||
#define TIM_PSC(timer) TIM_REGISTER_AT(timer, 0x28)
|
||||
|
||||
// TIM auto-reload register
|
||||
#define TIM_ARR(timer) TIM_REGISTER_AT(timer, 0x2C)
|
||||
|
||||
// TIM capture/compare register 1
|
||||
#define TIM_CCR1(timer) TIM_REGISTER_AT(timer, 0x34)
|
||||
|
||||
// TIM capture/compare register 2
|
||||
#define TIM_CCR2(timer) TIM_REGISTER_AT(timer, 0x38)
|
||||
|
||||
|
||||
// TIM break and dead-time register
|
||||
|
||||
#define TIM_BDTR(timer) TIM_REGISTER_AT(timer, 0x44)
|
||||
|
||||
|
||||
#define TIM_MOE (1<<15)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user