Got the encoder to work

+ added encoder mode support in timer driver
+ added external IRQ support in io driver
+ created 3D model for encoder cap
* tweaked ui lib for testing purposes
This commit is contained in:
Steins7 2020-02-02 22:20:10 +01:00
parent 3c7a09479c
commit 6baa7b0bbb
11 changed files with 211 additions and 133 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ bin
*tags
*.taghl
*.~lock*
*.stl

34
cad/encoder.scad Normal file
View File

@ -0,0 +1,34 @@
//$fn = 100;
r = 12;
h = 12;
center_r = 3.2;
mol_r = 7;
mol_off = 6;
difference() {
union() {
difference() {
cylinder(h=h, r=r, center=true);
translate([0,0,h/2])
cylinder(h=15, r=center_r, center=true);
for(i=[0:45:359]) {
echo((r+mol_off*sin(i)));
translate([(r+mol_off)*cos(i),(r+mol_off)
*sin(i),0])
cylinder(h=h, r=mol_r, center=true);
}
}
translate([3,0,0])
cube([3,2*center_r,h], center=true);
}
difference() {
translate([0,0,0.7])
cylinder(h=h, r=0.8*r, center=true);
translate([0,0,0.7])
cylinder(h=h, r=1.4*center_r, center=true);
}
}

View File

@ -87,15 +87,15 @@ void EXTI15_10_IRQHandler() {
}
/* Definitions for EXTI configuration */
#define SYSCFG_EXTI_PA_MASK 0
#define SYSCFG_EXTI_PB_MASK 1
#define SYSCFG_EXTI_PC_MASK 2
#define SYSCFG_EXTI_PD_MASK 3
#define SYSCFG_EXTI_PE_MASK 4
#define SYSCFG_EXTI_PH_MASK 7
enum io_exti_mask {
SYSCFG_EXTI_PA_MASK = 0x0,
SYSCFG_EXTI_PB_MASK = 0x1,
SYSCFG_EXTI_PC_MASK = 0x2,
SYSCFG_EXTI_PD_MASK = 0x3,
SYSCFG_EXTI_PE_MASK = 0x4
};
int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint8_t pin_cfg, OnIO cb) {
int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint16_t pin_cfg, OnIO cb) {
// enable GPIOx subsystem clocking
if (gpio == GPIOA) RCC->APB2ENR |= 1<<2;
@ -107,9 +107,7 @@ int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint8_t pin_cfg, OnIO cb) {
// setup pin mask for crx registers
uint64_t pin_mask = 0;
for(int i=0; i<16; ++i) {
if((pin >> i) & 0x1) {
pin_mask |= 0x1ll << 4*i;
}
if((pin >> i) & 0x1) pin_mask |= 0x1ll << 4*i;
}
// clear previous data
@ -121,111 +119,96 @@ int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint8_t pin_cfg, OnIO cb) {
// set up the new configuration
crx = pin_mask * (pin_cfg & 0xF);
odr = pin_cfg & 0x10;
odr = pin * ((pin_cfg & 0x10) >> 4);
gpio->CRH |= crx >> 32;
gpio->CRL |= crx & 0xFFFFFFFF;
gpio->BSRR |= odr;
//if (!cb) return -1; //no callback attached
return 0;
//TODO manage alternate functions
// if (pin_cfg & 0x3) return -1; //callback set, but not in input mode
//
// // ************* Input GPIO + External IRQ *************
//
// uint32_t port_mask = 0;
// manage IRQs //TODO allow IRQ reset
if (!cb) return 0; //no callback attached
if (pin_cfg & 0x7) return -1; //callback set, but not in input mode
RCC->APB2ENR |= 0x1; //enable AFIO clocking
// prepare mask
uint8_t port_mask = 0;
// uint32_t pin_mask = 0;
//
// if (gpio == GPIOA) port_mask = SYSCFG_EXTI_PA_MASK;
// else if (gpio == GPIOB) port_mask = SYSCFG_EXTI_PB_MASK;
// else if (gpio == GPIOC) port_mask = SYSCFG_EXTI_PC_MASK;
// else if (gpio == GPIOD) port_mask = SYSCFG_EXTI_PD_MASK;
// else if (gpio == GPIOE) port_mask = SYSCFG_EXTI_PE_MASK;
//
// uint32_t bit_mask = 0x1;
//
// for (int i=0; i<16; i++) {
// if (pin_mask & bit_mask) {
// // enable clock for SYSCFG, no need for EXTI (interface not clocked)
// RCC->APB2ENR = RCC->APB2ENR | (1<<14);
//
// // configure pin Px_i (4 pin config per EXTICR[] register, 4 bits per pin)
// // use port Px and bind Px_i --> EXTIi
// // i>>2 = i/4 ; i & 0x3 = i%4
// gpio->EXTICR[i>>2] = (SYSCFG->EXTICR[i>>2] &
// ~(0x0000000F << ((i & 3)<<2))) |
// (port_mask << ((i & 3)<<2));
//
// // allow pin EXTIi to send an IRQ
// EXTI->IMR = EXTI->IMR | bit_mask;
// // not a wakeup event
// EXTI->EMR = EXTI->EMR & (~bit_mask);
//
// // Configure pin event IRQ on rising (RTSR)/falling (FTSR) edge (rising only here)
// if (pin_cfg & PIN_OPT_IRQ_EDGE_RISE) {
// EXTI->RTSR = EXTI->RTSR | bit_mask;
// } else {
// EXTI->RTSR = EXTI->RTSR & (~bit_mask);
// }
//
// if (pin_cfg & PIN_OPT_IRQ_EDGE_FALL) {
// EXTI->FTSR = EXTI->FTSR | bit_mask;
// } else {
// EXTI->FTSR = EXTI->FTSR & (~bit_mask);
// }
//
// io_cb[i] = cb;
//
// // reset any pending IRQ on PC13
// EXTI->PR = bit_mask;
//
// // Setup NVIC
// switch (i) {
// case 0:
// NVIC_SetPriority(EXTI0_IRQn, EXTI0_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI0_IRQn);
// break;
// case 1:
// NVIC_SetPriority(EXTI1_IRQn, EXTI1_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI1_IRQn);
// break;
// case 2:
// NVIC_SetPriority(EXTI2_IRQn, EXTI2_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI2_IRQn);
// break;
// case 3:
// NVIC_SetPriority(EXTI3_IRQn, EXTI3_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI3_IRQn);
// break;
// case 4:
// NVIC_SetPriority(EXTI4_IRQn, EXTI4_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI4_IRQn);
// break;
// case 5:
// case 6:
// case 7:
// case 8:
// case 9:
// NVIC_SetPriority(EXTI9_5_IRQn, EXTI9_5_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI9_5_IRQn);
// break;
// case 10:
// case 11:
// case 12:
// case 13:
// case 14:
// case 15:
// NVIC_SetPriority(EXTI15_10_IRQn, EXTI15_10_IRQ_PRIORITY);
// NVIC_EnableIRQ(EXTI15_10_IRQn);
// break;
// default:
// return 0;
//}
//}
//bit_mask = bit_mask<<1;
//}
if (gpio == GPIOA) port_mask = SYSCFG_EXTI_PA_MASK;
else if (gpio == GPIOB) port_mask = SYSCFG_EXTI_PB_MASK;
else if (gpio == GPIOC) port_mask = SYSCFG_EXTI_PC_MASK;
else if (gpio == GPIOD) port_mask = SYSCFG_EXTI_PD_MASK;
else if (gpio == GPIOE) port_mask = SYSCFG_EXTI_PE_MASK;
// setup external IRQ lines
uint16_t afio_mask;
for(int i=0; i<4; ++i) {
afio_mask = ((pin_mask & (0xFFFF << i)) >> i) * port_mask;
if(afio_mask) AFIO->EXTICR[i] |= afio_mask;
}
// clear pending IRQs on concerned lines
EXTI->PR |= pin;
// configure IRQ options and masks
EXTI->IMR |= pin;
if(pin_cfg & 0x100) EXTI->RTSR |= pin;
if(pin_cfg & 0x200) EXTI->FTSR |= pin; //in case both falling and rising
//are set, both will be a trigger
// register IRQ callbacks
for(int i=0; i<16; ++i) {
if((pin >> i) & 0x1) {
io_cb[i] = cb;
// Setup NVIC
switch (i) {
case 0:
NVIC_SetPriority(EXTI0_IRQn, EXTI0_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI0_IRQn);
break;
case 1:
NVIC_SetPriority(EXTI1_IRQn, EXTI1_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI1_IRQn);
break;
case 2:
NVIC_SetPriority(EXTI2_IRQn, EXTI2_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI2_IRQn);
break;
case 3:
NVIC_SetPriority(EXTI3_IRQn, EXTI3_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI3_IRQn);
break;
case 4:
NVIC_SetPriority(EXTI4_IRQn, EXTI4_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI4_IRQn);
break;
case 5:
case 6:
case 7:
case 8:
case 9:
NVIC_SetPriority(EXTI9_5_IRQn, EXTI9_5_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI9_5_IRQn);
break;
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
NVIC_SetPriority(EXTI15_10_IRQn, EXTI15_10_IRQ_PRIORITY);
NVIC_EnableIRQ(EXTI15_10_IRQn);
break;
default:
return -1; //impossible to get there
}
}
}
return 0;
}

View File

@ -70,11 +70,14 @@ enum io_conf {
// PIN_OPT_AF15 0xF
//};
///* irq pin option */
//#define PIN_OPT_IRQ_EDGE_RISE (1 << 12)
//#define PIN_OPT_IRQ_EDGE_FALL (2 << 12)
//#define PIN_OPT_IRQ_EDGE_BOTH (3 << 12)
//
//------------------------------------------------------------------------------
/* GPIO IRQ conf definitons */
enum io_irq_conf {
IO_IRQ_EDGE_RISE = (0x1 << 8),
IO_IRQ_EDGE_FALL = (0x2 << 8),
IO_IRQ_EDGE_BOTH = (0x3 << 8)
};
typedef void (*OnIO)();
//------------------------------------------------------------------------------
@ -85,7 +88,7 @@ typedef void (*OnIO)();
* function 'cb' if not NULL.
* returns 0 if success
*/
int io_configure(GPIO_TypeDef *gpio, uint16_t pin_mask, uint8_t pin_cfg,
int io_configure(GPIO_TypeDef *gpio, uint16_t pin_mask, uint16_t pin_cfg,
OnIO cb);
/* io_read

View File

@ -94,7 +94,7 @@ int lcd_init(TIM_TypeDef* tim, uint8_t col, uint8_t row) {
// disable JTAG, as it utilise needed pins, SWD remains usable in
// synchronous mode
RCC->APB2ENR |= 0x1;
RCC->APB2ENR |= 0x1; //enable AFIO clocking
AFIO->MAPR = (AFIO->MAPR & ~(0x8 << 24)) | 0x2 << 24;
// configure the lcd control pins
@ -182,3 +182,4 @@ void lcd_print_c(char c) {
void lcd_set_cursor(uint8_t col, uint8_t row) {
lcd_send_cmd(LCD_DDRAM_ADDR | (col + rows_offset[row]));
}

View File

@ -268,3 +268,38 @@ void timer_stop(TIM_TypeDef *tmr) {
tmr->CR1 &= !1;
}
//------------------------------------------------------------------------------
int timer_enc_init(TIM_TypeDef* tmr) {
// enable timer
if (tmr == TIM1) {
RCC->APB2ENR |= 1<<11;
} else if (tmr == TIM2) {
RCC->APB1ENR |= 1<<0;
} else if (tmr == TIM3) {
RCC->APB1ENR |= 1<<1;
} else if (tmr == TIM4) {
RCC->APB1ENR |= 1<<2;
} else return -1; //no such timer
//TODO set registers at reset value
tmr->SMCR |= 0x1; //count on only one edge
tmr->ARR = (1 << 16)-1;
// map inputs
tmr->CCMR1 |= 0x9;
tmr->CCMR1 |= 0x9 << 8;
// enable input channels
tmr->CCER |= 0x1;
tmr->CCER |= 0x1 << 4;
tmr->CR1 |= 0x1; //enable timer
return 0;
}

View File

@ -41,6 +41,9 @@ void timer_start(TIM_TypeDef *tmr);
*/
void timer_stop(TIM_TypeDef *tmr);
//------------------------------------------------------------------------------
int timer_enc_init(TIM_TypeDef* tmr);
//------------------------------------------------------------------------------
//#define PWM_CHANNEL_1 0
//#define PWM_CHANNEL_2 1

View File

@ -16,6 +16,7 @@ Clock_t sysclks;
//------------------------------------------------------------------------------
/* static variables */
int val = 0;
int count = 0;
uint16_t data = 0;
int16_t voltage = 0;
int16_t temp = 0;
@ -24,7 +25,14 @@ int16_t temp = 0;
/* Timer IRQ */
static void timeout_cb(void) {
io_write(GPIOC, val, PIN_13);
io_write(GPIOB, val, PIN_12);
val = !val;
data = adc_read(ADC1, 2);
data -= adc_read(ADC1, 3);
}
static void enc_button_cb(void) {
count = !count;
}
//------------------------------------------------------------------------------
@ -36,7 +44,11 @@ int main(void) {
// configure GPIO for LED
if(io_configure(GPIOC, PIN_13, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0))
return 0;
if(io_configure(GPIOB, PIN_12, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0))
return 0;
io_write(GPIOC, 1, PIN_13);
io_write(GPIOB, 1, PIN_12);
// configure GPIOS for temperature sensors
if(io_configure(GPIOA, PIN_0 | PIN_1 | PIN_2 | PIN_3 | PIN_4 | PIN_5,
@ -52,6 +64,13 @@ int main(void) {
lcd_send_cmd(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | LCD_CTRL_CUR_OFF |
LCD_CTRL_BLINK_OFF);
// configure encoder
io_configure(GPIOB, PIN_6 | PIN_7, IO_MODE_INPUT | IO_IN_FLOATING, 0);
timer_enc_init(TIM4);
io_configure(GPIOB, PIN_8, IO_MODE_INPUT | IO_IN_PULL_UP |
IO_IRQ_EDGE_FALL, enc_button_cb);
// start timed interruption
timer_tick_init(TIM2, 1000, timeout_cb);
timer_start(TIM2);
@ -59,13 +78,15 @@ int main(void) {
// main loop
while(1){
// update T1
data = adc_read(ADC1, 0);
data -= adc_read(ADC1, 1);
//data = adc_read(ADC1, 0);
//data -= adc_read(ADC1, 1);
voltage = ((data*4) << 8)/4095;
temp = ((voltage - 0x73) << 8)/0x9;
//voltage = ((data*4) << 8)/4095;
//temp = ((voltage - 0x73) << 8)/0x9;
update_temp(T1, temp);
uint32_t pin = io_read(GPIOB, PIN_8);
if(!pin) count = !count;
if(count) update_temp(T1, (int16_t)TIM4->CNT/2);
// update T2
data = adc_read(ADC1, 2);

View File

@ -1,5 +1,10 @@
#include "ui.h"
static uint8_t temp_pos[][2] = {
{11, 0},
{ 2, 1},
{11, 1}};
void update_temp(uint8_t id, int16_t t) {
if(id > 2) return; //protect from overflow
@ -7,7 +12,7 @@ void update_temp(uint8_t id, int16_t t) {
// prepare data
char str[16]; //longer, in case of error
t = t >> 8;
//t = t >> 8;
// convert int into str
uint32_t nb = num2str(str, t, 10);

View File

@ -19,14 +19,6 @@ enum temp {
T2 = 2
};
/** temp_pos
* coords of the temprature ids
*/
static uint8_t temp_pos[][2] = {
{11, 0},
{ 2, 1},
{11, 1}};
/** update_temp
* update on the lcd the given value for the corresponding id
*/

View File

@ -18,7 +18,7 @@ uint32_t num2str(char *s, int number, uint8_t base) {
*s='\0';
// reverse string
uint32_t cnt = s - p;
int cnt = s - p;
char tmp;
for(int i=0; i<cnt/2; ++i) {
tmp = p[i];