Move source code to firmware directory

This commit is contained in:
2020-11-13 11:18:21 +01:00
parent ed34a0a578
commit bc9ad5f8cc
13 changed files with 0 additions and 0 deletions

43
firmware/debounce.c Normal file
View File

@@ -0,0 +1,43 @@
#include <avr/io.h>
#include "debounce.h"
#include "ptimer.h"
void SuperDebounce(uint8_t * key_state, volatile uint8_t *KPIN,
uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,
void (*push_proc)(void), void (*rep_proc)(void) ) {
enum {idle, debounce, go_rep, wait_rep, rep};
if(!rep_time) rep_time=20;
if(!rep_wait) rep_wait=150;
uint8_t key_press = !(*KPIN & key_mask);
if( key_press && !*key_state ) {
*key_state = debounce;
timers[TIM_DEBOUNCE] = 15;
} else
if( *key_state ) {
if( key_press && debounce==*key_state && !timers[TIM_DEBOUNCE] ) {
*key_state = 2;
timers[TIM_DEBOUNCE]=5;
} else
if( !key_press && *key_state>1 && *key_state<4 ) {
if(push_proc) push_proc(); /* KEY_UP */
*key_state=idle;
} else
if( key_press && go_rep==*key_state && !timers[TIM_DEBOUNCE] ) {
*key_state = wait_rep;
timers[TIM_DEBOUNCE]=rep_wait;
} else
if( key_press && wait_rep==*key_state && !timers[TIM_DEBOUNCE] ) {
*key_state = rep;
} else
if( key_press && rep==*key_state && !timers[TIM_DEBOUNCE] ) {
timers[TIM_DEBOUNCE] = rep_time;
if(rep_proc) rep_proc(); /* KEY_REP */
}
}
if( *key_state>=3 && !key_press ) *key_state = idle;
}

36
firmware/debounce.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef __DEBOUNCE_H__
#define __DEBOUNCE_H__
/************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************
* AUTOR: Mirosław Kardaś
* ZALETY:
* - nie wprowadza najmniejszego spowalnienia
* - posiada funkcję REPEAT (powtarzanie akcji dla dłużej wciśniętego przycisku)
* - można przydzielić róne akcje dla trybu REPEAT i pojedynczego kliknięcia
* - można przydzielić tylko jedną akcję wtedy w miejsce drugiej przekazujemy 0 (NULL)
*
* Wymagania:
* Timer programowy utworzony w oparciu o Timer sprzętowy (przerwanie 100Hz)
*
* Parametry wejściowe:
*
* *key_state - wskaźnik na zmienną w pamięci RAM (1 bajt) - do przechowywania stanu klawisza
* *KPIN - nazwa PINx portu na którym umieszczony jest klawisz, np: PINB
* key_mask - maska klawisza np: (1<<PB3)
* rep_time - czas powtarzania funkcji rep_proc w trybie REPEAT
* rep_wait - czas oczekiwania do przejścia do trybu REPEAT
* push_proc - wskaźnik do własnej funkcji wywoływanej raz po zwolenieniu przycisku
* rep_proc - wskaźnik do własnej funkcji wykonywanej w trybie REPEAT
**************************************************************************************/
void SuperDebounce( uint8_t* key_state,
volatile uint8_t* KPIN,
uint8_t key_mask,
uint16_t rep_time,
uint16_t rep_wait,
void (*push_proc)(void),
void (*rep_proc)(void)
);
#endif

60
firmware/i2c.c Normal file
View File

@@ -0,0 +1,60 @@
#include <avr/io.h>
#include "i2c.h"
void i2c_init(uint32_t bitrate)
{
uint8_t prescaler_options[] = {1, 4, 16, 64};
uint8_t prescaler_value = prescaler_options[TWSR & 0x03]; // 0x03 (hex) = 0b00000011 (bin)
TWBR = (uint8_t)((F_CPU / bitrate - 16) / (2 * prescaler_value));
}
void i2c_start(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
while(!(TWCR & (1<<TWINT)));
}
void i2c_stop(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
while(TWCR & (1<<TWSTO));
}
uint8_t i2c_read(uint8_t ack)
{
TWCR = (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
void i2c_write(uint8_t byte)
{
TWDR = byte;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
}
void i2c_readbuf(uint8_t sla, uint8_t adr, uint8_t len, uint8_t* buf)
{
i2c_start();
i2c_write(sla);
i2c_write(adr);
i2c_start();
i2c_write(sla + I2C_READ);
while(len--) *buf++ = i2c_read(len ? I2C_ACK : I2C_NACK);
i2c_stop();
}
void i2c_writebuf(uint8_t sla, uint8_t adr, uint8_t len, uint8_t* buf)
{
i2c_start();
i2c_write(sla);
i2c_write(adr);
while (len--)
{
i2c_write(*buf++);
}
i2c_stop();
}

16
firmware/i2c.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef __I2C_H__
#define __I2C_H__
#define I2C_ACK 1
#define I2C_NACK 0
#define I2C_READ 1
void i2c_init(uint32_t bitrate);
void i2c_start(void);
void i2c_stop(void);
uint8_t i2c_read(uint8_t ack);
void i2c_write(uint8_t byte);
void i2c_readbuf(uint8_t sla, uint8_t adr, uint8_t len, uint8_t* buf);
void i2c_writebuf(uint8_t sla, uint8_t adr, uint8_t len, uint8_t* buf);
#endif

38
firmware/keyboard.c Normal file
View File

@@ -0,0 +1,38 @@
#include <avr/io.h>
#include "keyboard.h"
#include "debounce.h"
#include "rtc.h"
#include "led.h"
uint8_t k_inc_hour, k_inc_minute, k_inc_second;
void inc_hour(void)
{
led_hour = (led_hour + 1) % 24;
rtc_set_time(HOUR, led_hour);
}
void inc_minute(void)
{
led_minute = (led_minute + 1) % 60;
rtc_set_time(MINUTE, led_minute);
}
void inc_second(void)
{
led_second = (led_second + 1) % 60;
rtc_set_time(SECOND, led_second);
}
void keyboard_init(void)
{
KEYBOARD_DIR &= ~(KEY_INC_HOUR | KEY_INC_MINUTE | KEY_INC_SECOND);
PORTB |= KEY_INC_HOUR | KEY_INC_MINUTE | KEY_INC_SECOND;
}
void keyboard_handle_input(void)
{
SuperDebounce(&k_inc_hour, &KEYBOARD_PIN, KEY_INC_HOUR, 20, 500, &inc_hour, &inc_hour);
SuperDebounce(&k_inc_minute, &KEYBOARD_PIN, KEY_INC_MINUTE, 20, 500, &inc_minute, &inc_minute);
SuperDebounce(&k_inc_second, &KEYBOARD_PIN, KEY_INC_SECOND, 20, 500, &inc_second, &inc_second);
}

14
firmware/keyboard.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__
#define KEYBOARD_DIR DDRB
#define KEYBOARD_PIN PINB
#define KEYBOARD_PORT PORTB
#define KEY_INC_HOUR (1<<PB0)
#define KEY_INC_MINUTE (1<<PB1)
#define KEY_INC_SECOND (1<<PB2)
void keyboard_init(void);
void keyboard_handle_input(void);
#endif

77
firmware/led.c Normal file
View File

@@ -0,0 +1,77 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include "led.h"
#define SET_LED(PORT, IDX, NUM) PORT = ((PORT & ~(1<<(IDX))) | (~(NUM) & 1<<(IDX)))
volatile uint8_t led_hour;
volatile uint8_t led_minute;
volatile uint8_t led_second;
void led_init(void)
{
// Set outputs
ANODES_DIR |= HOUR_ANODE | MINUTE_ANODE | SECOND_ANODE;
LED0_DIR |= LED0;
LED1_DIR |= LED1;
LED2_DIR |= LED2;
LED3_DIR |= LED3;
LED4_DIR |= LED4;
LED5_DIR |= LED5;
// Clear LEDs
ANODES_PORT = HOUR_ANODE | MINUTE_ANODE | SECOND_ANODE;
LED0_PORT |= LED0;
LED1_PORT |= LED1;
LED2_PORT |= LED2;
LED3_PORT |= LED3;
LED4_PORT |= LED4;
LED5_PORT |= LED5;
TCCR0 |= (1<<WGM01); // CTC Mode
TCCR0 |= (1<<CS02) | (1<<CS00); // Prescaler 1024
OCR0 = 38; // 200Hz
TIMSK |= (1<<OCIE0); // Enable CTC interruptions
}
ISR(TIMER0_COMP_vect)
{
static uint8_t counter = 1;
switch(counter) {
case 1:
ANODES_PORT = ~HOUR_ANODE;
SET_LED(LED0_PORT, 0, led_hour);
SET_LED(LED1_PORT, 1, led_hour);
SET_LED(LED2_PORT, 2, led_hour);
SET_LED(LED3_PORT, 3, led_hour);
SET_LED(LED4_PORT, 4, led_hour);
SET_LED(LED5_PORT, 5, led_hour);
break;
case 2:
ANODES_PORT = ~MINUTE_ANODE;
SET_LED(LED0_PORT, 0, led_minute);
SET_LED(LED1_PORT, 1, led_minute);
SET_LED(LED2_PORT, 2, led_minute);
SET_LED(LED3_PORT, 3, led_minute);
SET_LED(LED4_PORT, 4, led_minute);
SET_LED(LED5_PORT, 5, led_minute);
break;
case 4:
ANODES_PORT = ~SECOND_ANODE;
SET_LED(LED0_PORT, 0, led_second);
SET_LED(LED1_PORT, 1, led_second);
SET_LED(LED2_PORT, 2, led_second);
SET_LED(LED3_PORT, 3, led_second);
SET_LED(LED4_PORT, 4, led_second);
SET_LED(LED5_PORT, 5, led_second);
break;
}
counter <<= 1;
if(counter > 4)
{
counter = 1;
}
}

35
firmware/led.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef __LED_H__
#define __LED_H__
#define LED0_PORT PORTA
#define LED0_DIR DDRA
#define LED0 (1<<0)
#define LED1_PORT PORTA
#define LED1_DIR DDRA
#define LED1 (1<<1)
#define LED2_PORT PORTA
#define LED2_DIR DDRA
#define LED2 (1<<2)
#define LED3_PORT PORTA
#define LED3_DIR DDRA
#define LED3 (1<<3)
#define LED4_PORT PORTA
#define LED4_DIR DDRA
#define LED4 (1<<4)
#define LED5_PORT PORTA
#define LED5_DIR DDRA
#define LED5 (1<<5)
#define ANODES_PORT PORTD
#define ANODES_DIR DDRD
#define HOUR_ANODE (1<<PD5)
#define MINUTE_ANODE (1<<PD6)
#define SECOND_ANODE (1<<PD7)
extern volatile uint8_t led_hour;
extern volatile uint8_t led_minute;
extern volatile uint8_t led_second;
void led_init(void);
#endif

37
firmware/main.c Normal file
View File

@@ -0,0 +1,37 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include "keyboard.h"
#include "ptimer.h"
#include "i2c.h"
#include "rtc.h"
#include "led.h"
#define I2C_BITRATE 100000UL // 100kHz
int main()
{
keyboard_init();
ptimer_init();
i2c_init(I2C_BITRATE);
rtc_int0_init();
led_init();
sei();
led_hour = 0;
led_minute = 0;
led_second = 0;
while(1)
{
keyboard_handle_input();
}
}
ISR(INT0_vect)
{
struct time curr_time = rtc_read_time();
led_hour = curr_time.hour;
led_minute = curr_time.minute;
led_second = curr_time.second;
}

23
firmware/ptimer.c Normal file
View File

@@ -0,0 +1,23 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include "ptimer.h"
volatile uint16_t timers[TIMERS_COUNT];
void ptimer_init(void)
{
for(uint8_t i=0; i<TIMERS_COUNT; ++i) timers[i] = 0;
TCCR2 |= (1<<WGM21); // CTC Mode
TCCR2 |= (1<<CS22) | (1<<CS21) | (1<<CS20); // Prescaler 1024
OCR2 = 78; // ~100Hz
TIMSK |= (1<<OCIE2); // Enable CTC interruptions
}
ISR(TIMER2_COMP_vect)
{
for(uint8_t i=0; i<TIMERS_COUNT; ++i)
{
if(timers[i]) --timers[i];
}
}

11
firmware/ptimer.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef __PTIMER_H__
#define __PTIMER_H__
#define TIMERS_COUNT 1
#define TIM_DEBOUNCE 0
extern volatile uint16_t timers[TIMERS_COUNT];
void ptimer_init(void);
#endif

37
firmware/rtc.c Normal file
View File

@@ -0,0 +1,37 @@
#include <avr/io.h>
#include "rtc.h"
#include "i2c.h"
void rtc_int0_init(void)
{
INT0_DIR &= ~(1<<INT0_PIN);
INT0_PORT |= (1<<INT0_PIN);
GICR |= (1<<INT0);
}
void rtc_int1_init(void)
{
INT1_DIR &= ~(1<<INT1_PIN);
INT1_PORT |= (1<<INT1_PIN);
GICR |= (1<<INT1);
}
void rtc_set_time(uint8_t part, uint8_t value)
{
uint8_t bcd = DEC_2_BCD(value);
i2c_writebuf(RTC_I2C_ADDR, part, 1, &bcd);
}
struct time rtc_read_time(void)
{
uint8_t buffer[3];
i2c_readbuf(RTC_I2C_ADDR, 0x02, 3, buffer);
struct time curr_time = {
BCD_2_DEC(buffer[2]),
BCD_2_DEC(buffer[1]),
BCD_2_DEC(buffer[0])
};
return curr_time;
}

33
firmware/rtc.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef __RTC_H__
#define __RTC_H__
#define RTC_I2C_ADDR 0xA2
#define SECOND 0x02
#define MINUTE 0x03
#define HOUR 0x04
#define INT0_PORT PORTD
#define INT0_DIR DDRD
#define INT0_PIN PD2
#define INT1_PORT PORTD
#define INT1_DIR DDRD
#define INT1_PIN PD3
#define DEC_2_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10))
#define BCD_2_DEC(bcd) (((((bcd) >> 4) & 0x0F) * 10) + ((bcd) & 0x0F))
struct time
{
uint8_t hour;
uint8_t minute;
uint8_t second;
};
void rtc_int0_init(void);
void rtc_int1_init(void);
void rtc_set_time(uint8_t part, uint8_t value);
struct time rtc_read_time(void);
#endif