Last active
May 3, 2018 03:47
-
-
Save SyncChannel/839ff3d346a632fc8910 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* REF-0 Standalone Operation | |
* Device: Atmel ATTINY841 | |
* Written in Atmel Studio 6 | |
* Created: 8/11/2015 8:56:28 AM | |
* Author: Dan Watson | |
* | |
* Pinout: | |
* PB1 (pin 3): PPS input | |
* PA1 (pin 12): Serial out to REF-0 (has to go through an inverter) | |
* PA6 (pin 7): Pulses high during PPS (for an LED) | |
*/ | |
// CPU running at 16 MHz (External TCXO) | |
#define F_CPU 16000000UL | |
// Defines for USART setup | |
#define USART_BAUDRATE 9600 | |
#define BAUD_PRESCALE ((F_CPU / (USART_BAUDRATE * 16UL)) - 1)a | |
// Four includes are needed for this program | |
#include <avr/io.h> | |
#include <stdio.h> | |
#include <avr/interrupt.h> | |
#include <util/delay.h> | |
// Motorola Oncore messages | |
// If you add more code and run out of RAM, store these in PROGMEM instead | |
uint8_t Ea[76] = { 0x40, 0x40, 0x45, 0x61, 0x01, 0x01, 0x07, 0xCE, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x08, | |
0x02, 0x08, 0xFF, 0x82, 0x04, 0x08, 0xFF, 0x82, 0x06, 0x08, | |
0xFF, 0x82, 0x08, 0x08, 0xFF, 0x82, 0x0A, 0x08, 0xFF, 0x82, | |
0x0C, 0x08, 0xFF, 0x82, 0x0E, 0x08, 0xFF, 0x82, 0x10, 0x08, | |
0xFF, 0x82, 0x20, 0xDF, 0x0D, 0x0A }; | |
uint8_t En[69] ={ 0x40, 0x40, 0x45, 0x6E, 0x01, 0x01, 0x00, 0xC0, 0x01, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | |
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, | |
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, | |
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, | |
0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, | |
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x0D, 0x0A }; | |
uint8_t Bb[92] = { 0x40, 0x40, 0x42, 0x62, 0x0A, 0x02, 0x00, 0x00, 0x5A, 0x00, | |
0x00, 0x00, 0x04, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x06, | |
0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x5A, | |
0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, | |
0x0C, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, | |
0x5A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x5A, 0x00, 0x00, | |
0x00, 0x12, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x14, 0x00, | |
0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, | |
0x0D, 0x0A }; | |
uint8_t Ap[25] = { 0x40, 0x40, 0x41, 0x70, 0x32, 0x61, 0x52, 0x99, 0x00, 0x81, | |
0x01, 0x2A, 0x0F, 0x54, 0xEB, 0x8B, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x38, 0x0D, 0x0A }; | |
uint8_t Aw[8] = { 0x40, 0x40, 0x41, 0x77, 0x00, 0x36, 0x0D, 0x0A }; | |
uint8_t Bj[8] = { 0x40, 0x40, 0x42, 0x6A, 0x00, 0x28, 0x0D, 0x0A }; | |
uint8_t Az[11] = { 0x40, 0x40, 0x41, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x0D, | |
0x0A }; | |
uint8_t At[8] = { 0x40, 0x40, 0x41, 0x74, 0x01, 0x34, 0x0D, 0x0A }; | |
uint8_t Bo[8] = { 0x40, 0x40, 0x42, 0x6F, 0x00, 0x2D, 0x0D, 0x0A }; | |
uint8_t Ag[8] = { 0x40, 0x40, 0x41, 0x67, 0x0A, 0x2C, 0x0D, 0x0A }; | |
//Misc variables | |
volatile uint8_t gotPPS = 0; | |
uint8_t messageRotation = 0; | |
// Declare functions | |
void sendByte(uint8_t val); | |
void advanceSecond(); | |
void sendMessages(); | |
int main(void) | |
{ | |
DDRA = 0b01000000; // Set Data Direction Register A, Pin A6 output | |
DDRB = 0b00000000; // Set Data Direction Register B | |
// Set up INT0 interrupt, on Pin B1 | |
MCUCR |= (1 << ISC01) | (1 << ISC00); // Interrupt on INT0 rising edge | |
GIMSK |= (1 << INT0); // Enable INT0 | |
// Set up USART 0 | |
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); // Set 8 bit characters for USART 0 | |
UBRR0H = (BAUD_PRESCALE >> 8); // Set baud rate on USART 0 | |
UBRR0L = BAUD_PRESCALE; | |
UCSR0B = (1 << TXEN0) | (1 << RXEN0); // Enable Tx and Rx on USART 0 | |
sei(); // Enable interrupts | |
while(1) | |
{ | |
if (gotPPS == 1) | |
{ | |
PORTA |= (1 << PINA6); | |
_delay_ms(75); | |
advanceSecond(); | |
sendMessages(); | |
PORTA ^= (1 << PINA6); | |
gotPPS = 0; | |
} | |
} | |
return 0; | |
} | |
ISR(INT0_vect) | |
{ | |
gotPPS = 1; | |
} | |
void sendByte(uint8_t val) | |
{ | |
UDR0 = val; | |
while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Wait for Tx to complete | |
} | |
void advanceSecond() | |
{ | |
Ea[73] = Ea[73] ^ Ea[10]; // XOR the seconds out of the check character | |
Ea[10]++; // Increment seconds | |
if (Ea[10] == 60) // If we reached 59 seconds, XOR the minute out | |
{ // of the check character and increment | |
Ea[10] = 0; | |
Ea[73] = Ea[73] ^ Ea[9]; | |
Ea[9]++; | |
if (Ea[9] == 60) // If we reached 59 minutes, XOR the hour out | |
{ // of the check character and increment | |
Ea[9] = 0; | |
Ea[73] = Ea[73] ^ Ea[8]; | |
Ea[8]++; | |
if (Ea[8] == 24) // If it's midnight, set hours to zero | |
{ | |
Ea[8] = 0; | |
} | |
Ea[73] = Ea[73] ^ Ea[8]; // XOR the new hours back in to the check character | |
} | |
Ea[73] = Ea[73] ^ Ea[9]; // XOR the new minutes back into the check character | |
} | |
Ea[73] = Ea[73] ^ Ea[10]; // XOR the new seconds back into the check character | |
} | |
void sendMessages() | |
{ | |
for (int j = 0; j < 76; j++) sendByte(Ea[j]); | |
for (int j = 0; j < 69; j++) sendByte(En[j]); | |
messageRotation++; // Cycle message rotation | |
if (messageRotation >= 30) messageRotation = 0; | |
if (messageRotation % 2 == 0) // Send @@Bb every two seconds | |
{ | |
for (int i = 0; i < 92; i++) sendByte(Bb[i]); | |
} | |
if (messageRotation % 5 == 0) // Send @@Ap every five seconds | |
{ | |
for (int i = 0; i < 25; i++) sendByte(Ap[i]); | |
} | |
if (messageRotation % 20 == 0) // Send @@Aw every 20 seconds | |
{ | |
for (int i = 0; i < 8; i++) sendByte(Aw[i]); | |
} | |
switch(messageRotation) { // Distribute the other messages throughout | |
case 8: // the 30 second period of rotation | |
for (int i = 0; i < 8; i++) sendByte(Bj[i]); // I chose seconds arbitrarily... | |
break; | |
case 13: | |
for (int i = 0; i < 11; i++) sendByte(Az[i]); | |
break; | |
case 17: | |
for (int i = 0; i < 8; i++) sendByte(At[i]); | |
break; | |
case 23: | |
for (int i = 0; i < 8; i++) sendByte(Bo[i]); | |
break; | |
case 27: | |
for (int i = 0; i < 8; i++) sendByte(Ag[i]); | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment