You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.2 KiB
C

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include "pinout.h"
#include "uart.h"
#include "i2cmaster.h"
#include "DS3231.h"
#include "menu.h"
#include "display.h"
#define RX_INPUT_BUFFER_SIZE 92
void check_dip_switches(void);
void setup(void);
void set_PWM_duty(int dutycycle);
int8_t parse_nmea_gps(char input_string[RX_INPUT_BUFFER_SIZE], uint8_t output_buffer[3]){
char* token = strsep(&input_string, ",");
if(!strcmp("$GPRMC", token)){
char* time = strsep(&input_string, ",");
if(!strlen(time)){
// no valid time available
return -2;
}
// craft bcd values
output_buffer[2] = (time[0] - 48) << 4;
output_buffer[2] |= time[1] - 48;
output_buffer[1] = (time[2] - 48) << 4;
output_buffer[1] |= time[3] - 48;
output_buffer[0] = (time[4] - 48) << 4;
output_buffer[0] |= time[5] - 48;
return 0;
}
return -1;
}
int main(void){
setup();
printf("Moin\n\r");
while(1){
check_dip_switches();
if(get_menu_active()){
PORTC &= ~DOT;
string_to_buffer(get_menu_text());
_delay_ms(10);
}
else{
uint8_t clock[3];
cli();
DS3231_read(clock);
sei();
// convert from bcd and back
int8_t hour = (10 * (clock[2] & 0xF0)>>4) + (clock[2] & 0x0F);
hour += menu_val_timezone;
hour %= 24;
if(hour < 0)
hour = 24 + hour;
clock[2] = ((hour/10)<<4)|(hour % 10);
clock_to_buffer(clock);
PORTC = (PORTC & (~DOT)) | (clock[0]%2) << 4; // blink dots
_delay_ms(100);
}
print_SR_Buffer();
}
}
void check_dip_switches() {
if (PINB & DIP_1) {
PORTC |= ENABLE_TUBE_PSU;
PORTA &= ~ENABLE_TUBE_SUPPLY;
// PORTB |= STATUS_LED_B;
} else {
PORTC &= ~(ENABLE_TUBE_PSU);
PORTA |= (ENABLE_TUBE_SUPPLY);
// PORTB &= ~STATUS_LED_B;
}
}
void setup(){
DDRA = ENABLE_TUBE_SUPPLY;
DDRB = STATUS_LED_B
| STATUS_LED_C
| MOSI
| CLK;
DDRC = LATCH_SR
| ENABLE_SR
| DOT
| ENABLE_TUBE_PSU;
DDRD = RESET_SR
| TUBE_LED;
//--------------------------
// SPI
//--------------------------
SPCR = (1 << SPE) | //enable SPI
(1 << MSTR) | //SPI als Master starten
(1 << SPR0) | //clock-prescaler LSB
(1 << SPR1) | //clock-prescaler MSB
(0 << SPIE) | //complete transfer/ recive interrupt
(0 << CPOL) |
(0 << CPHA) |
(0 << DORD); //MSB first = 0
SPSR = (1 << SPI2X);// | //clock- prescaler double speed
PORTC &= ~LATCH_SR; //latch low, sonst startet SPI nicht
PORTC |= LATCH_SR;
PORTD |= RESET_SR; //Setzte Reset auf HIGH (active LOW)
PORTC &= ~(ENABLE_SR); //Aktiviert Shiftregister (active LOW)
//--------------------------
// Externe Interrupts
//--------------------------
//External Interrupt Mask Register
EIMSK |= (1 << INT0) | //Aktiviere Interrupt INT0
(1 << INT1); //Aktiviere Interrupt INT1
//External Interrupt Control Register A
EICRA |= (0 << ISC10) | //Interrupt bei jedem Pegelwechsel auf INT1
(1 << ISC11) |
(1 << ISC00) | //Interrupt bei jedem Pegelwechsel auf INT0
(1 << ISC01);
//--------------------------
// Timer + Zeitinterrupts
//--------------------------
//PWM-Timer
//OC2A set when upcounting, clear when down counting
TCCR2A = (1<<COM2A1)
|(0<<COM2A0);
TCCR2A |= (1<<WGM20) //Wave form generartion mode
|(0<<WGM21); // Wave form generation mode
TCCR2B = (1 << CS22)
|(0 << CS21)
|(0 << CS20);
OCR2A = 0; // Compare value 125
uart_init();
i2c_init();
sei(); //Enable Interrupts
clear_SR_Buffer();
}
//Encoder rotate
ISR(INT0_vect) {
if (PIND & ENCODER_B) {
if(get_menu_active())
menu_up_down(1);
else
OCR2A++;
} else {
if(get_menu_active())
menu_up_down(-1);
else
OCR2A--;
}
}
//Encoder Button
ISR(INT1_vect) {
printf("button\n\r");
enter_menu();
}
ISR(USART0_RX_vect)
{
PORTB ^= STATUS_LED_C;
static char async_input_buffer[RX_INPUT_BUFFER_SIZE];
static uint8_t async_buffer_pointer = 0;
uint8_t data = UART_DATA_REG;
if(!(data == '\n' || data == '\r')){
async_input_buffer[async_buffer_pointer]=data;
async_buffer_pointer++;
}
else if(async_buffer_pointer > 0){
async_input_buffer[async_buffer_pointer] = 0; // Null terminate string
async_buffer_pointer=0;
uint8_t gps_time[3];
int8_t err = parse_nmea_gps(async_input_buffer, gps_time);
if(!err){
PORTB |= STATUS_LED_C;
//if(rtc_time[0] != gps_time[0] || rtc_time[1] != gps_time[1] || rtc_time[2] != gps_time[2])
DS3231_write(gps_time);
}
else if(err == -2)
PORTB &= ~STATUS_LED_C;
}
}