sdp-dry-sensor/platform.c
2022-08-23 13:34:34 +03:00

164 lines
3.7 KiB
C

//
// Created by vlad on 17.08.22.
//
#include "platform.h"
#include "config.h"
#include <avr/io.h>
#include <avr/interrupt.h>
static char systick_flag;
uint16_t sensor_1;
uint16_t sensor_2;
ISR(TIMER1_OVF_vect) {
systick_flag = 1;
// LED2_Toggle();
}
void platform_init() {
// инициализация GPIO
DDRD = INIT_DDRD;
DDRB = INIT_DDRB;
DIDR = 0x03; // отключение цифрового ввода/вывода на входах компаратора
// инициализация юарта
uart_init();
// инициализация таймера 1 (16-ти битный)
systick_flag = 0;
// mode=14 (FastPWM, top in ICR1), x64, ICR1=1000000/64=15625
TCCR1B = (1 << WGM13) | (1 << WGM12);
TCCR1A = (1 << WGM11);
// выставляем TOP
ICR1 = (uint16_t)(F_CPU / 64);
// разрешаем прерывание по переполнению
TIMSK |= (1 << TOV1);
TCCR1B |= (1 << CS11) | (1 << CS10); // выставляем x64, то есть запускаем таймер
sei();
}
void platform_wait_for_interrupt() {
// для режима сна Idle нужно отрубить компаратор (в даташите просили)
// в других режимах сна он отрубается автоматически
char acsr = ACSR;
ACSR |= (1 << ACD); // чтобы отрубить компаратор нужно записать 1 в этот бит
MCUCR |= (1 << SE);
asm volatile ("sleep");
MCUCR &= ~(1 << SE);
// восстанавливаем состояние компаратора
ACSR |= acsr;
}
void systick_sync() {
systick_flag = 0; // можно не запрещать прерывания: операция атомарна
for(;;) {
cli();
char flag = systick_flag;
if (flag) {
systick_flag = 0;
}
// else {
// platform_wait_for_interrupt();
// }
sei();
if (flag) {
return;
}
}
}
void uart_init() {
// U2X=1, baud=9600, error=0.2%, f=1M
UBRRH = 0;
UBRRL = 12;
UCSRA = (1 << U2X);
UCSRB = (1 << TXEN) | (1 << RXEN);
}
void uart_deinit() {
UCSRB = 0; // снимаем RXEN и TXEN
}
void uart_write_char(char c) {
while ((UCSRA & (1 << UDRE)) == 0)
;
UDR = c;
}
void uart_write_str(const char* str) {
while (1) {
char c = *(str++);
if (c == '\0') {
break;
}
uart_write_char(c);
}
}
void uart_write_fstr(PGM_P str) {
while (1) {
char c = pgm_read_byte(str++);
if (c == '\0') {
break;
}
uart_write_char(c);
}
}
char uart_read_char() {
while (!(UCSRA & (1 << RXC)))
;
return UDR;
}
void uart_discard_input() {
while (UCSRA & (1 << RXC)) {
char __attribute__((__unused__)) _tmp = UDR;
}
}
void platform_read_sensors() {
EXTPWR_EN_Set();
systick_sync();
sensor_1 = 0;
sensor_2 = 0;
uint8_t states = FRQ_Gpio & (FRQ1_Pin | FRQ2_Pin);
for(;;) {
uint8_t tmp = FRQ_Gpio;
if ((tmp & FRQ1_Pin) != (states & FRQ1_Pin)) {
states = (states & (~FRQ1_Pin)) | tmp;
sensor_1++;
}
if ((tmp & FRQ2_Pin) != (states & FRQ2_Pin)) {
states = (states & (~FRQ2_Pin)) | tmp;
sensor_2++;
}
cli();
char flag = systick_flag;
if (flag) {
systick_flag = 0;
}
sei();
if (flag) {
break;
}
}
EXTPWR_EN_Reset();
// быстрое деление на 2 (считалось каждое изменение)
sensor_2 >>= 1;
sensor_1 >>= 1;
}