#include <stdlib.h>
#include "rtc.h"
#define HV_EN_PIN PB1
#define HV_BL_PIN PB2
#define HV_POL_PIN PB4
#define HV_LATCH_PIN PB6
#define HV_DATA_PIN PB7
#define HV_CLK_PIN PB5
#define NIX_DIM_PIN PD7
#define HV_DATA_PIN_HIGH PORTB |= (1 << HV_DATA_PIN)
#define HV_DATA_PIN_LOW PORTB &= ~(1 << HV_DATA_PIN)
#define ENABLE_HV_PWR PORTB |= (1 << HV_EN_PIN)
#define DISABLE_HV_PWR PORTB &= ~(1 << HV_EN_PIN)
volatile uint8_t get_time_flag = 0;
volatile uint8_t time_sent_flag = 0;
volatile uint8_t increment_hours = 0;
volatile uint8_t increment_minutes = 0;
volatile uint8_t lid_state = 0;
volatile uint8_t set_time_mode = 0;
volatile uint16_t current_time = 0;
volatile unsigned long timer3_counter = 0;
uint8_t serialized_digits_arry[64] = {0};
rtc_t rtc;
void setup() {
CLKPR = 0x80;
CLKPR |= 0x01;
initGPIO();
initInterrupts();
RTC_Init();
Serial.begin(9600); // start serial for output
Serial.println("Started");
rtc.hour = 0b00000000; // 10:40:20 am
rtc.min = 0x00;
rtc.sec = 0x00;
RTC_SetDateTime(&rtc);
startTimer2();
RTC_GetDateTime(&rtc);
}
void loop() {
displayTime(); //Get time from RTC and format to send to HV Chip
setTime();
// if(!rtc.hour && !rtc.min && (rtc.sec < 30)){
// cleanTubes();
// }
delay(250);
}
void initGPIO(void){
DDRB |= (1 << HV_DATA_PIN) | (1 << HV_LATCH_PIN) | (1 << HV_POL_PIN) | (1 << HV_BL_PIN) | (1 << HV_EN_PIN)| (1 << HV_CLK_PIN); // Set 180V Enable and HV Serial to Parallel data lines to outputs
DDRD |= (1 << NIX_DIM_PIN); // Set HV Data CLK and NIX_DIM to outputs
//PORTD |= (1 << HV_CLK_PIN); //Set HV_CLK_PIN to idle High
//PORTB |= (1 << HV_BL_PIN);
}
void initInterrupts(void){
//Setup External Interrupts
EICRA = (1 << ISC20) | (1 << ISC21) | (1 << ISC30) | (1 << ISC31); //Enable Interrupts 0,1 to trigger on rising edge
EIMSK = (1 << INT3) | (1 << INT2); //Enable Interrupts
//Setup PCInts
PCICR = (1 << PCIE1); //Enable Pin Change interrupt 1
PCMSK1 = (1 << PCINT13); //Enable PCINT13
//Setup Timer 0
TIMSK0 |= (1 << TOIE0); //set Timer/Counter0 Overflow Interrupt Enable - This timer checks time from RTC when int triggered
//Setup Timer 1
TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10); //Set Timer 1 to fast PWM 10bit mode and OC1A to clear pin on compare match
TCCR1B |= (1 << WGM12);
TIMSK1 |= (1 << TOIE1); //set Timer/Counter1 Overflow Interrupt Enable - This timer does something (exits time set mode) after time expires
OCR1A = 512; //Set OCR1A to make 50% duty cycle
//Setup Timer 2
TCCR2A |= (1 << COM2A1) | (1 << WGM21) | (1 << WGM20); //Clear OC2A on Compare Match, set OC2A at BOTTOM, (non-inverting mode). This timer is for Nixie Dimming
OCR2A = 200; //Initialize output compare register to full brightness
//Setup Timer3
TCCR3A = 0x00;
TCCR3B = 0x00;
TIMSK3 = (1 << TOIE3); //set Timer/Counter3 Overflow Interrupt Enable - This timer is used for timing space between button pushes
// //Setup Analog Comparator Int
// ADCSRB |= (1 << ACME); //Route ADC0 input to negative input for analog comparator
// ACSR |= (1 << ACIS1) | (1 << ACIS0) | (1 << ACIE); //Enable Comparator interrupt and sets Comparator interrupt on rising edge - may need to change depending on datasheet for therm sensor
sei(); //Enable global interrupts
}
void setTime(void){
if(set_time_mode){
if(increment_hours){
rtc.hour += 1;
increment_hours = 0;
delay(10);
}
if(increment_minutes){
rtc.min += 1;
increment_minutes = 0;
delay(10);
}
RTC_SetDateTime(&rtc);
}
}
void displayTime(void){
RTC_GetDateTime(&rtc);
char buff0[2];
char buff1[2];
char buff2[2];
char buff3[2];
uint8_t digits_arry[4] = {0};
for(int i = 0; i < 64; i++){
serialized_digits_arry[i] = 0;
}
digits_arry[0] = (rtc.hour & 0x30) >> 4;
digits_arry[1] = rtc.hour & 0x0F;
digits_arry[2] = (rtc.min & 0x70) >> 4;
digits_arry[3] = rtc.min & 0x0F;
Serial.print(digits_arry[0]);
Serial.print(digits_arry[1]);
Serial.print(":");
Serial.print(digits_arry[2]);
Serial.println(digits_arry[3]);
if(digits_arry[0] == 1 && (digits_arry[1] > 2)){
digits_arry[0] = 0;
digits_arry[1] -= 2;
}
else if(digits_arry[0] == 2){
switch(digits_arry[1]){
case 0:
digits_arry[0] = 0;
digits_arry[1] = 8;
break;
case 1:
digits_arry[0] = 0;
digits_arry[1] = 9;
break;
case 2:
digits_arry[0] = 1;
digits_arry[1] = 0;
break;
case 3:
digits_arry[0] = 1;
digits_arry[1] = 1;
break;
}
}
else if((digits_arry[0] == 0) && (digits_arry[1] == 0)) {
digits_arry[0] = 1;
digits_arry[1] = 2;
}
// itoa(digits_arry[0], buff0, 10);
// itoa(digits_arry[1], buff1, 10);
// itoa(digits_arry[2], buff2, 10);
// itoa(digits_arry[3], buff3, 10);
// serial.print(buff0);
// serial.print(buff1);
// serial.print(buff2);
// serial.println(buff3);
//hours tens
switch (digits_arry[0]){
case 0:
serialized_digits_arry[42] = 1;
break;
case 1:
serialized_digits_arry[40] = 1;
break;
}
//hours_ones
switch (digits_arry[1]){
case 0:
serialized_digits_arry[58] = 1;
break;
case 1:
serialized_digits_arry[57] = 1;
break;
case 2:
serialized_digits_arry[56] = 1;
break;
case 3:
serialized_digits_arry[54] = 1;
break;
case 4:
serialized_digits_arry[52] = 1;
break;
case 5:
serialized_digits_arry[50] = 1;
break;
case 6:
serialized_digits_arry[49] = 1;
break;
case 7:
serialized_digits_arry[51] = 1;
break;
case 8:
serialized_digits_arry[53] = 1;
break;
case 9:
serialized_digits_arry[55] = 1;
break;
}
//Min tens
switch (digits_arry[2]){
case 0:
serialized_digits_arry[10] = 1;
break;
case 1:
serialized_digits_arry[8] = 1;
break;
case 2:
serialized_digits_arry[7] = 1;
break;
case 3:
serialized_digits_arry[9] = 1;
break;
case 4:
serialized_digits_arry[12] = 1;
break;
case 5:
serialized_digits_arry[14] = 1;
break;
}
//min ones
switch (digits_arry[3]){
case 0:
serialized_digits_arry[26] = 1;
break;
case 1:
serialized_digits_arry[25] = 1;
break;
case 2:
serialized_digits_arry[24] = 1;
break;
case 3:
serialized_digits_arry[22] = 1;
break;
case 4:
serialized_digits_arry[20] = 1;
break;
case 5:
serialized_digits_arry[18] = 1;
break;
case 6:
serialized_digits_arry[17] = 1;
break;
case 7:
serialized_digits_arry[19] = 1;
break;
case 8:
serialized_digits_arry[21] = 1;
break;
case 9:
serialized_digits_arry[23] = 1;
break;
}
//for(int i = 0; i < 64; i++){
// char buff[2];
// itoa(serialized_digits_arry[i], buff, 10);
// serial.print(buff);
//}
//serial.println("");
startTimer1();
}
void cleanTubes(void){
for(int i = 0; i < 5; i++){
for(int j = 0; j < 32; j++) {
Serial.println("In 1st for");
serialized_digits_arry[j] = 1;
serialized_digits_arry[j + 8] = 1;
serialized_digits_arry[j + 16] = 1;
serialized_digits_arry[j + 32] = 1;
startTimer1();
delay(100);
serialized_digits_arry[j] = 0;
serialized_digits_arry[j + 8] = 0;
serialized_digits_arry[j + 16] = 0;
serialized_digits_arry[j + 32] = 0;
}
for(int j = 32; j >= 0; j--) {
Serial.println("In 2nd for");
serialized_digits_arry[j] = 1;
serialized_digits_arry[j + 8] = 1;
serialized_digits_arry[j + 16] = 1;
serialized_digits_arry[j + 32] = 1;
startTimer1();
delay(1);
serialized_digits_arry[j] = 0;
serialized_digits_arry[j + 8] = 0;
serialized_digits_arry[j + 16] = 0;
serialized_digits_arry[j + 32] = 0;
}
RTC_GetDateTime(&rtc);
delay(10);
}
}
void startTimer0(void){
TCNT0 = 0; //Clear timer register
TCCR0B |= (1 << CS02); //Set clock select bits to CLKio/256 and start timer
}
void startTimer1(void){
TCNT1 = 0;
TCCR1B = (1 << CS10); //Set timer select to CLKio/8 and start timer 1
}
void startTimer2(void){
TCNT2 = 0;
TCCR2B |= (1 << CS21); //Set clock select bit to clkt2s/1024 and start timer
}
void startTimer3(void){
TCNT3 = 0;
TCCR3B |= (1 << CS31); //Set clock select bit to clkt2s/1024 and start timer
}
void stopTimer0(void){
TCCR0B &= 0b11111000;
}
void stopTimer1(void){
TCCR1B &= 0b11111000;
}
void stopTimer3(void){
TCCR3B &= 0b11111000;
}
// ISR(TIM0_OVF_vect){
// get_time_flag = 1;
// }
ISR(INT2_vect){
Serial.print("");
//If button is pressed and the clock isn't running and not in set_time_mode, start timer for second press timeout
if(!(TCCR3B & 0x07) && !set_time_mode){
startTimer3();
}
//If button pressed and the timer is running (second press) and it hasn't timed out and not already in set_time_mode then put into set time mode
else if((TCCR3B & 0x07) && (timer3_counter <= 300) && !set_time_mode){
set_time_mode = 1;
}
//If in set time mode and button pressed, increment hours by 1
else if(set_time_mode){
timer3_counter = 0;
increment_hours = 1;
}
}
ISR(INT3_vect){
Serial.print("");
if(set_time_mode){
timer3_counter = 0;
increment_minutes = 1;
}
}
ISR(TIMER1_OVF_vect){
static int counter = 0;
if(!counter)
PORTB &= ~(1 << HV_LATCH_PIN);
if(serialized_digits_arry[counter])
{
HV_DATA_PIN_HIGH;
//Serial.print("1");
}
else
{
HV_DATA_PIN_LOW;
//Serial.print("0");
}
counter++;
if(counter == 64)
{
PORTB |= (1 << HV_LATCH_PIN); //Latch data out
stopTimer1(); //Stop Timer1
counter = 0; //Reset counter variable
time_sent_flag = 1;
//Serial.println("");
}
}
ISR(TIMER3_OVF_vect){
static int time_val = 10;
timer3_counter++;
static int blink_counter = 0;
//Serial.print("Timer3 counter: ");
//Serial.println(timer3_counter);
//If not in set time mode and timer times out then stop timer
if((timer3_counter > time_val) && !set_time_mode){
stopTimer3();
timer3_counter = 0;
Serial.println("time out");
}
//Every half second, if in set time mode and have been in set time mode for less than 5 seconds, toggle HV_Enable to blink display
if(set_time_mode && blink_counter == 10){
PORTB ^= (1 << HV_BL_PIN);
blink_counter = 0;
}
//If in set_time_mode for longer than 5 seconds without user input then exit set_time_mode
if(set_time_mode && (timer3_counter > (time_val*30))){
stopTimer3();
PORTB &= ~(1 << HV_BL_PIN);
set_time_mode = 0;
timer3_counter = 0;
}
blink_counter++;
}