Last active
December 23, 2019 17:40
-
-
Save nerdralph/4f2439af784fb08ab06e9fbcd378d98f to your computer and use it in GitHub Desktop.
prototype MicroCore OSCCAL tuner for ATtiny13
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
// t13 OSCCAL tuner | |
// Ralph Doncaster 2019 public domain software | |
// repeatedly press 'x' until OSCCAL value stabilizes | |
// output value is timing delta in cycles followed by OSCCAL | |
#define BAUD_RATE 115200 | |
#include <BBUart.h> | |
#include <avr/sleep.h> | |
#define UART_RX 1 | |
//extern int UART_RX; | |
#define DEBUGPIN 4 | |
// converts 4-bit nibble to ascii hex | |
uint8_t nibbletohex(uint8_t value) | |
{ | |
value &= 0x0F; | |
if ( value > 9 ) value += 'A' - ':'; | |
return value + '0'; | |
} | |
uint8_t printHex(uint8_t value) | |
{ | |
TxByte(nibbletohex(value>>4)); | |
TxByte(nibbletohex(value)); | |
} | |
ISR(INT0_vect) | |
{ | |
PINB |= 1<<DEBUGPIN; // toggle DEBUGPIN | |
// start timer when pin transitions low | |
if ((PINB & 1<<UART_RX) == 0) | |
TCCR0B = 1<<CS00; | |
else { | |
uint8_t current = TCNT0; | |
// end of interval, reset counter | |
TCCR0B = 0; | |
TCNT0 = 0; | |
// 'x' begins with 3 zeros + start bit = 4 | |
// match speed to soft uart timing of 7 + TXDELAYCONT * 3 | |
uint8_t expected = 4 * (7 + TXDELAYCOUNT * 3); | |
//uint8_t ideal_target = 4 * F_CPU / BAUD_RATE; | |
char delta = expected - current; | |
if (delta > 4) OSCCAL++; | |
if (delta < -4) OSCCAL--; | |
asm("lpm"); // 3 cycle delay | |
printHex(delta); | |
TxByte(' '); | |
printHex(OSCCAL); | |
TxByte('\n'); | |
} | |
// clear interrupt flag in case another triggered | |
GIFR = 1<<INTF0; | |
} | |
void setup() { | |
// soft uart tx is PB3 | |
digitalWrite(3,HIGH); | |
pinMode(3,OUTPUT); | |
pinMode(DEBUGPIN,OUTPUT); | |
MCUCR |= 1 << SE; // sleep enable | |
digitalWrite(UART_RX,HIGH); // pullup | |
delay(1000); // pause after startup | |
wait_x: | |
TxByte('x'); | |
TxByte('\n'); | |
// wait for tuning character to ensure not reading noise | |
// before entering tuning mode | |
uint8_t counter = 0; | |
while (PINB & (1<<UART_RX)); | |
do { | |
counter++; | |
} while ((PINB & (1<<UART_RX)) == 0); | |
// low period should be 4 bit-times for 'x' | |
// counter loop is 4 cycles, so counter =~ BIT_CYCLES | |
uint8_t margin = BIT_CYCLES/8; | |
if ( counter - (uint8_t)BIT_CYCLES > margin ) goto wait_x; | |
else | |
if ( (uint8_t)BIT_CYCLES - counter > margin ) goto wait_x; | |
delay(1); // skip remaining bits in frame | |
TxByte('I'); // debug enabling INTO | |
printHex(OSCCAL); | |
TxByte('\n'); | |
// reset counter for first interrupt | |
TCCR0B = 0; | |
TCNT0 = 0; | |
// setup interrupt on Rx pin, any change on INTO | |
GIMSK = 1<<INT0; | |
MCUCR |= (1<<ISC00); | |
sei(); | |
} | |
void loop() { | |
// nothing to see here | |
asm("sleep"); | |
//sleep_cpu(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
v3 changes:
switch from digitalRead() to direct register reading to ensure fastest port reading.
reset timer/counter before enabling ISR