Interrupt driven RTTY

master
Philip Heron 2010-06-16 21:02:24 +01:00
rodzic 3d9b7b7d7d
commit d841092e74
3 zmienionych plików z 43 dodań i 38 usunięć

Wyświetl plik

@ -35,7 +35,7 @@ int main(void)
while(1) while(1)
{ {
rtx_string("Hello, World!\n");
} }
return(0); return(0);

78
rtty.c
Wyświetl plik

@ -10,76 +10,82 @@
#include "config.h" #include "config.h"
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <string.h>
#define RTTY_DELAY (1000000 / RTTY_BAUD) #include "rtty.h"
/* MARK = Upper tone, Idle, bit */ /* MARK = Upper tone, Idle, bit */
#define TXENABLE (0x04) #define TXENABLE (0x04)
#define MARK (0x02) #define MARK (0x02)
#define SPACE (0x01) #define SPACE (0x01)
/* RTTY speed */ #define TXBIT(b) PORTB = (PORTB & ~(MARK | SPACE)) | (b)
uint16_t rtty_delay = (1000000 / RTTY_BAUD);
//#define RTTY_DELAY rtty_delay
void rtx_baud(int baud) volatile uint8_t *txbuf = 0;
{ volatile uint16_t txlen = 0;
rtty_delay = 1000000 / baud;
}
inline void rtx_bit(uint8_t b) ISR(TIMER0_COMPA_vect)
{ {
PORTB = (PORTB & ~(MARK | SPACE)) | b; /* The currently transmitting byte, including framing */
} static uint8_t byte = 0x00;
static uint8_t bit = 0x00;
void rtx_byte(uint8_t byte)
{
int i;
/* Start bit */ uint8_t b = 0;
rtx_bit(SPACE); switch(bit++)
_delay_us(RTTY_DELAY);
/* 7 bit */
for(i = 0; i < 8; i++)
{ {
if(byte & 1 << i) rtx_bit(MARK); else rtx_bit(SPACE); case 0: b = 0; break; /* Start bit */
_delay_us(RTTY_DELAY); case 9: b = 1; break; /* Stop bit */
case 10: b = 1; TCNT0 += OCR0A >> 1; bit = 0; break; /* Stop bit 0.5 */
default: b = byte & 1; byte >>= 1; break;
} }
/* Stop bit 1 */ TXBIT(b ? MARK : SPACE);
rtx_bit(MARK);
_delay_us(RTTY_DELAY); if(bit == 0 && txlen > 0)
_delay_us(RTTY_DELAY / 2); {
byte = *(txbuf++);
txlen--;
}
} }
void rtx_string(char *s) void rtx_string(char *s)
{ {
while(*s != '\0') rtx_byte(*(s++)); uint16_t length = strlen(s);
rtx_wait();
txbuf = (uint8_t *) s;
txlen = length;
} }
void rtx_string_P(PGM_P s) void rtx_string_P(PGM_P s)
{ {
char b; //char b;
while((b = pgm_read_byte(s++)) != '\0') rtx_byte(b); //while((b = pgm_read_byte(s++)) != '\0') rtx_byte(b);
} }
void rtx_data(uint8_t *data, size_t length) void rtx_data(uint8_t *data, size_t length)
{ {
int b; rtx_wait();
for(b = 0; b < length; b++) rtx_byte(data[b]); txbuf = data;
txlen = length;
} }
void rtx_wait() void rtx_wait()
{ {
/* TODO: Wait for interrupt driven TX to finish */ /* Wait for interrupt driven TX to finish */
while(txlen > 0);
} }
void rtx_init() void rtx_init()
{ {
/* We use Port B pins 1, 2 and 3 - MARK by default */ /* RTTY is driven by TIMER0 in CTC mode */
rtx_bit(MARK); TCCR0A = _BV(WGM01); /* Mode 2, CTC */
TCCR0B = _BV(CS02) | _BV(CS00); /* prescaler 1024 */
OCR0A = F_CPU / 1024 / RTTY_BAUD;
TIMSK0 = _BV(OCIE0A); /* Enable interrupt */
/* We use Port B pins 1, 2 and 3 */
TXBIT(MARK);
PORTB |= TXENABLE; PORTB |= TXENABLE;
DDRB |= MARK | SPACE | TXENABLE; DDRB |= MARK | SPACE | TXENABLE;
} }

1
rtty.h
Wyświetl plik

@ -13,7 +13,6 @@
#include <stdint.h> #include <stdint.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
extern void rtx_baud(int baud);
extern void rtx_string(char *s); extern void rtx_string(char *s);
extern void rtx_string_P(PGM_P s); extern void rtx_string_P(PGM_P s);
extern void rtx_data(uint8_t *data, size_t length); extern void rtx_data(uint8_t *data, size_t length);