#include "stdint.h"
#include "stdlib.h"
#include "stdbool.h"
#include "stm8s.h"
#include "stm8s_gpio.h"
#include "stm8s_tim2.h"
#include "stm8s_tim4.h"
#include "stm8s_clk.h"
#include "stm8s_it.h"
#include "stm8s_exti.h"
/*
A
___ A - PD1
| | B - PD4 DIG1 - PC7
F| G |B C - PB4 DIG2 - PA3
|___| D - PC5 DIG3 - PD6
| | E - PC6 DIG4 - PC3
E| D |C F - PD5
|___| . G - PB5
. - PC4
0bABCDEFG.
0 - 0b00000011
1 - 0b10011111
2 - 0b00100101
3 - 0b00001101
4 - 0b10011001
5 - 0b01001001
6 - 0b01000001
7 - 0b00011111
8 - 0b00000001
9 - 0b00001001
*/
static uint16_t rpm=0;
bool timeout = false;
#define SAMPLES 8
static uint16_t periods[SAMPLES];
static uint32_t sum;
static uint8_t refresh_cnt;
#define DISP_PB(pin) ((0x00000100ull)<<(pin))
#define DISP_PC(pin) ((0x00010000ull)<<(pin))
#define DISP_PD(pin) ((0x01000000ull)<<(pin))
#define _DISP_V_PB(x) (((x)>>8) & 0xff)
#define _DISP_V_PC(x) (((x)>>16) & 0xff)
#define _DISP_V_PD(x) (((x)>>24) & 0xff)
#define DISP_IDX_PB 0
#define DISP_IDX_PC 1
#define DISP_IDX_PD 2
#define DISP_V(x) {_DISP_V_PB(x), _DISP_V_PC(x), _DISP_V_PD(x)}
#define SEG_A DISP_PD(1)
#define SEG_B DISP_PD(4)
#define SEG_C DISP_PB(4)
#define SEG_D DISP_PC(5)
#define SEG_E DISP_PC(6)
#define SEG_F DISP_PD(5)
#define SEG_G DISP_PB(5)
#define SEG_DOT DISP_PC(4)
#define SEG_ALL (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DOT)
void print(){
static uint8_t led_disp;
static const uint16_t digit_vals[4] = {1000, 100, 10, 1};
uint8_t digit;
static const uint8_t pins_symbol[10][3] = {
[0] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F ),
[1] = DISP_V( SEG_B | SEG_C ),
[2] = DISP_V(SEG_A | SEG_B | SEG_D | SEG_E | SEG_G),
[3] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_G),
[4] = DISP_V( SEG_B | SEG_C | SEG_F | SEG_G),
[5] = DISP_V(SEG_A | SEG_C | SEG_D | SEG_F | SEG_G),
[6] = DISP_V(SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G),
[7] = DISP_V(SEG_A | SEG_B | SEG_C ),
[8] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G),
[9] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G),
};
static const uint8_t pins_all[3] = DISP_V(SEG_ALL);
if(rpm>9999) rpm = 9999;
digit = (rpm / digit_vals[led_disp]) % 10;
GPIOC->ODR &= ~GPIO_PIN_7;
GPIOA->ODR &= ~GPIO_PIN_3;
GPIOD->ODR &= ~GPIO_PIN_6;
GPIOC->ODR &= ~GPIO_PIN_3;
/* all cathodes high (off) */
/* GPIOA->ODR |= pins_all[DISP_IDX_PA]; */
GPIOB->ODR |= pins_all[DISP_IDX_PB];
GPIOC->ODR |= pins_all[DISP_IDX_PC];
GPIOD->ODR |= pins_all[DISP_IDX_PD];
/* GPIOA->ODR &= ~pins_symbol[digit][DISP_IDX_PA]; */
GPIOB->ODR &= ~pins_symbol[digit][DISP_IDX_PB];
GPIOC->ODR &= ~pins_symbol[digit][DISP_IDX_PC];
GPIOD->ODR &= ~pins_symbol[digit][DISP_IDX_PD];
switch(led_disp){
case 0:
GPIOC->ODR |= GPIO_PIN_7;
break;
case 1:
GPIOA->ODR |= GPIO_PIN_3;
break;
case 2:
GPIOD->ODR |= GPIO_PIN_6;
break;
case 3:
GPIOC->ODR |= GPIO_PIN_3;
break;
}
led_disp++;
if(led_disp > 3)
led_disp = 0;
}
void main(void)
{
GPIOA->ODR &= (~GPIO_PIN_3);
GPIOA->DDR |= GPIO_PIN_3;
/* Pull-Up or Push-Pull */
GPIOA->CR1 |= GPIO_PIN_3;
/* No external interrupt or No slope control */
GPIOA->CR2 &= (~GPIO_PIN_3);
GPIOB->ODR &= (~(GPIO_PIN_4|GPIO_PIN_5));
GPIOB->DDR |= (GPIO_PIN_4|GPIO_PIN_5);
GPIOB->CR1 |= (GPIO_PIN_4|GPIO_PIN_5);
GPIOB->CR2 &= (~(GPIO_PIN_4|GPIO_PIN_5));
GPIOC->ODR &= (~(
GPIO_PIN_3|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6|
GPIO_PIN_7));
GPIOC->DDR |= (
GPIO_PIN_3|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6|
GPIO_PIN_7);
GPIOC->CR1 |= (
GPIO_PIN_3|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6|
GPIO_PIN_7);
GPIOC->CR2 &= (~(
GPIO_PIN_3|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6|
GPIO_PIN_7));
GPIOD->ODR &= (~(
GPIO_PIN_1|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6));
GPIOD->DDR |= (
GPIO_PIN_1|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6);
GPIOD->CR1 |= (
GPIO_PIN_1|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6);
GPIOD->CR2 &= (~(
GPIO_PIN_1|
GPIO_PIN_4|
GPIO_PIN_5|
GPIO_PIN_6));
//sensor
/* Set Input mode */
GPIOD->DDR &= (~GPIO_PIN_2);
/* Pull-Up or Push-Pull */
GPIOD->CR1 |= GPIO_PIN_2;
/* Interrupt or Slow slope */
GPIOD->CR2 |= GPIO_PIN_2;
/* Enables Clock switch */
CLK->SWCR |= CLK_SWCR_SWEN;
/* Disables Switch interrupt */
CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIEN);
/* Selection of the target clock source */
CLK->SWR = CLK_SOURCE_HSE;
/* Wait until the target clock source is ready */
while((CLK->SWCR & CLK_SWCR_SWBSY) != 0 );
EXTI->CR1 &= (~EXTI_CR1_PDIS);
EXTI->CR1 |= (EXTI_SENSITIVITY_FALL_ONLY << 6);
CLK->PCKENR1 |= (1 << CLK_PERIPHERAL_TIMER4);
TIM4->IER |= TIM4_IT_UPDATE;
TIM4->PSCR = TIM4_PRESCALER_128;
TIM4->ARR = 255;
enableInterrupts();
TIM4->CR1 |= TIM4_CR1_CEN;
CLK->PCKENR1 |= (1 << CLK_PERIPHERAL_TIMER2 );
TIM2->PSCR = TIM2_PRESCALER_256;
TIM2->ARRH = 0xFF;
TIM2->ARRL = 0xFF;
TIM2->CCMR3 |= TIM2_ICSELECTION_DIRECTTI;
/* Select the Polarity */
TIM2->CCER2 |= TIM2_CCER2_CC3P;
/* Set the CCE Bit */
TIM2->CCER2 |= TIM2_CCER2_CC3E;
TIM2->IER |= TIM2_IT_UPDATE;
TIM2->CR1 |= TIM2_CR1_CEN;
while (1) {
if(refresh_cnt == 60){
refresh_cnt = 0;
if (timeout) {
rpm = 0;
} else{
rpm = (uint32_t)(62500 * 60 * SAMPLES) / sum;
}
}
}
}
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
refresh_cnt++;
print();
TIM4->SR1 = ~TIM4_IT_UPDATE;
}
INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6)
{
static uint8_t pos;
uint16_t current_period=0;
if(TIM2->SR1 & TIM2_FLAG_CC3){
current_period = ((uint16_t)TIM2->CCR3H << 8) | TIM2->CCR3L;
sum -= periods[pos];
periods[pos] = current_period;
sum += current_period;
if(++pos == SAMPLES)
{
pos = 0;
}
TIM2->SR1 = ~TIM2_FLAG_CC3;
timeout = false;
TIM2->CNTRH = 0;
TIM2->CNTRL = 0;
}
}
INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
{
timeout = true;
TIM2->SR1 = ~TIM2_IT_UPDATE;
}