Skip to content

Instantly share code, notes, and snippets.

@stecman
Last active October 18, 2024 22:51
Show Gist options
  • Save stecman/db3673a0ff9b0f002f2fb86b3cd5a2df to your computer and use it in GitHub Desktop.
Save stecman/db3673a0ff9b0f002f2fb86b3cd5a2df to your computer and use it in GitHub Desktop.
Hacked together serial-controlled pin power pulser (AVR)
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <stdlib.h>
#include <string.h>
void init_usart(void)
{
cli();
// Set baud rate to 9600 (with 16MHz clock)
UBRR0H = (uint8_t)(103 >> 8);
UBRR0L = (uint8_t)(103);
// Enable receiver and transmitter
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
// Set frame format: 8 data, 1 stop bit
UCSR0C = (3<<UCSZ00);
UCSR0C &= ~(1<<USBS0);
sei();
}
void usart_transmit(uint8_t data)
{
// Wait for empty transmit buffer
while ( !( UCSR0A & (1<<UDRE0)) );
// Put data into buffer, sends the data
UDR0 = data;
}
uint8_t usart_receive(void)
{
// Wait for data to be received
while ( !(UCSR0A & (1<<RXC0)) );
// Get and return received data from buffer
return UDR0;
}
void print(char* string)
{
uint8_t i = 0;
while (string[i] != '\0') {
usart_transmit(string[i]);
++i;
}
}
void println(char* string)
{
print(string);
usart_transmit('\n');
}
#define BUF_SIZE 10
char buffer[BUF_SIZE] = {} ;
int main(void)
{
// Recover from any watchdog timer reset mishaps
wdt_reset();
wdt_disable();
init_usart();
println("Microswitch Timer v0.1\r");
println("Copyright 1989, Some Guy");
println("\r\nEnter a value in tenths of milliseconds (100uS) or press enter to repeat the last value.\r\n");
int delay = 1;
for (;;) {
print("> ");
memset(buffer, NULL, BUF_SIZE);
for (int8_t i = 0; i < 9; ++i) {
char byte = usart_receive();
// Move back in buffer on backspace
if (byte =='\b') {
if (i > 1) i -= 2;
continue;
}
// Exit early on user submit
if (byte == '\f' || byte == '\n' || byte == '\r') {
print("\r\n");
break;
}
buffer[i] = byte;
}
// Update delay if a value was entered
if (buffer[0] != NULL) {
delay = atoi(buffer);
}
char outBuf[10];
itoa(delay, outBuf, 10);
print("Powering for ");
print(outBuf);
print("00 uS...\r\n");
if (delay < 1) {
println("(nothing to do...)\r\n");
continue;
}
// Stop timer (prescaler = 0)
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
// There are 68.717 ticks per millisecond with a 256 prescaler at 16MHz
//
// ((16000000/256)/(2^16-1)) * 1000 => 953.6888
// (2^16-1)/953.6888 => 68.717
//
uint16_t counterTarget = 7 * delay;
// Load value to count to
OCR1A = counterTarget;
// Reset timer to zero
TCNT1H = 0;
TCNT1L = 0;
// Clear compare flag
TIFR |= _BV(OCF1A);
// Enable port
DDRA = 0xFF;
PORTA = 0xFF;
// Start timer with 256 prescaler
TCCR1B |= _BV(CS12);
// Wait for timer to roll hit target
while ( (TIFR & _BV(OCF1A)) == 0 ) continue;
// Disable port
PORTA = 0x0;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment