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
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;
|
|
}
|
|
}
|
|
|