284 lines
7.2 KiB
C

#include "config.h"
#include "platform.h"
#include <util/delay.h>
#include <avr/interrupt.h>
#define SMS_END "\032\n"
#define SIM800_DELAY_TIME 100
static volatile uint8_t timer0_time;
ISR(TIMER0_OVF_vect) {
timer0_time++;
LED2_Toggle();
}
void sim800_wait_for(PGM_P str) {
PGM_P curr_pos = str;
LED1_Set();
while (1) {
char p = pgm_read_byte(curr_pos);
if (p == '\0') {
break;
}
char c = uart_read_char();
if (c == '\r') {
continue;
}
if (c == p) {
curr_pos++;
} else {
curr_pos = str;
}
}
LED1_Reset();
}
void sim800_wait_for_ok() {
sim800_wait_for(PSTR("OK\n"));
}
void sim800_start() {
LED2_Set();
GSM_EN_Set();
_delay_ms(1000);
// зажимаем кнопку на секунду
GSM_KEY_Set();
_delay_ms(1100);
GSM_KEY_Reset();
// еще 2 секунды на загрузку модуля
_delay_ms(3000);
// врубаем юарт
uart_init();
uart_write_fstr(PSTR("AT\n"));
sim800_wait_for_ok();
// вырубить echo mode (повторяет команду, которая прилетела) ATE0
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("ATE1\n")); // TODO поставить 0 чтобы модем лишнюю херню не слал
sim800_wait_for_ok();
// после готовности смс все сразу станет понятно
sim800_wait_for(PSTR("SMS Ready\n"));
while (1) {
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("AT+CREG?\n"));
sim800_wait_for(PSTR("+CREG: "));
char mode = uart_read_char();
uart_read_char(); // запятая
char status = uart_read_char();
if (mode == '0' && status == '1') {
break;
}
}
}
void sim800_stop() {
// вырубить модуль
uart_write_fstr(PSTR("AT+CPOWD=1\n"));
sim800_wait_for(PSTR("DOWN\n")); // придет NORMAL POWER DOWN
uart_deinit();
GSM_EN_Reset();
LED2_Reset();
}
uint16_t sim800_get_battery() {
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("AT+CBC\n"));
sim800_wait_for(PSTR("+CBC:"));
for (uint8_t i = 0; i < 2; i++) {
sim800_wait_for(PSTR(","));
}
// по идее тут будет напряжение
// 4 цифры, но мне не важно на самом деле сколько
uint16_t result = 0;
while (1) {
char c = uart_read_char();
if (c == ' ' || c == '\r') {
continue;
}
// туда попадет и символ конца строки
if (c < '0' || c > '9') {
break;
}
result *= 10;
result += c - '0';
}
// ждем ок, то есть конец команды
sim800_wait_for_ok();
return result;
}
void sim800_prepare_sms() {
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("AT+CMGF=1\n")); // PDU режим
sim800_wait_for_ok();
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("AT+CMGS=\"+79208109798\"\n")); // PDU режим
sim800_wait_for(PSTR(">"));
}
void sim800_wait_for_sms_send() {
sim800_wait_for(PSTR("+CMGS"));
}
static void num2buff(char* buffer, uint16_t num) {
int8_t len; // длинна числа
if (num < 10) len = 1;
else if (num < 100) len = 2;
else if (num < 1000) len = 3;
else if (num < 10000) len = 4;
else len = 5;
buffer[len] = '\0'; // вставляем конец строки
for (; len > 0; len--) {
uint8_t digit = (num % 10) + '0';
num /= 10;
buffer[len - 1] = (char)digit;
}
}
void sim800_send_telemetry() {
uint16_t bat = sim800_get_battery();
sim800_prepare_sms();
char buff[6];
// sprintf(buff, "F1=%d F2=%d\033\n", sensor_1, sensor_2);
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("F1="));
num2buff(buff, sensor_1);
uart_write_str(buff);
uart_write_fstr(PSTR(" F2="));
num2buff(buff, sensor_2);
uart_write_str(buff);
uart_write_fstr(PSTR(" BAT="));
num2buff(buff, bat);
uart_write_str(buff);
uart_write_fstr(PSTR(SMS_END));
sim800_wait_for_sms_send();
}
void read_sensors() {
timer0_time = 0;
EXTPWR_EN_Set();
register uint32_t s1 = 0, s2 = 0;
register uint8_t states = FRQ_Gpio & (FRQ1_Pin | FRQ2_Pin);
TCNT0 = 0;
TCCR0B |= (1 << CS02) | (1 << CS00); // x1024
while (timer0_time < 250) {
uint8_t tmp = FRQ_Gpio;
if ((tmp & FRQ1_Pin) != (states & FRQ1_Pin)) {
states = (states & (~FRQ1_Pin)) | tmp;
s1++;
}
if ((tmp & FRQ2_Pin) != (states & FRQ2_Pin)) {
states = (states & (~FRQ2_Pin)) | tmp;
s2++;
}
}
TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00)); // x0
EXTPWR_EN_Reset(); // отрубаем питание генераторов
// быстрое деление на 2 (считалось каждое изменение)
// 64 секунды * 2 = 128 (2^7)
sensor_2 = (uint16_t)(s1 >> 7);
sensor_1 = (uint16_t)(s2 >> 7);
// готово!
}
int main() {
platform_init();
LED2_Set();
_delay_ms(100);
LED2_Reset();
_delay_ms(10000);
// врубаем модем
sim800_start();
// рабочая отправка сообщений
sim800_prepare_sms();
_delay_ms(SIM800_DELAY_TIME);
uart_write_fstr(PSTR("I'm working!" SMS_END)); // сама смска
sim800_wait_for_sms_send();
// отправляем сразу же телеметрию
read_sensors();
sim800_send_telemetry();
// рубим модем
sim800_stop();
MCUCR |= (1 << SE);
systick_execution_enable = 1;
SP = RAMEND;
asm volatile (
"main_loop:\n"
"sleep\n"
"rjmp main_loop\n");
}
ISR(TIMER1_OVF_vect) {
static uint16_t time = 0;
static char exec = 0;
if (systick_execution_enable) {
time++;
if (SPEED_Gpio & SPEED_Pin) {
// (скорость отпущена, пин подтянут к питанию)
// если скорости нет, шлем смс раз в час
if (time > 60 * 60) {
if (!exec) {
time = 0;
exec = 1;
}
}
} else {
// если скорость зажата, то максимальное ожидание 5 минут
if (time > 300) {
if (!exec) {
time = 0;
exec = 1;
}
}
}
}
if (exec == 1) {
exec = 2;
MCUCR &= ~(1 << SE);
sei();
read_sensors();
sim800_start();
sim800_send_telemetry();
sim800_stop();
cli();
MCUCR |= (1 << SE);
exec = 0;
}
}