| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 | /* * Transmit an FM-modulated signal using the USART in SPI master mode. * As per ABC standard, this signal is transmitted MSB first. */#include "usbcas.h"#define BITS_PER_PATTERN_BYTE	2#define PATTERN_BIT_MASK	((1 << BITS_PER_PATTERN_BYTE) - 1)#include "fmpat.h"static uint8_t parity = 0;static uint8_t data;static uint8_t left;static inline bool fmtx_send_ready(void) ATTR_ALWAYS_INLINE;static inline bool fmtx_send_ready(void){	return !!(UCSR1A & (1 << UDRE1));}/* * Sends another chunk of output. */uint8_t fmtx_send_more(void){	uint8_t l = left;	if (!fmtx_send_ready())		return l;	/* Not ready yet */	uint8_t d = data;	uint8_t pattern = fm_pat[d & PATTERN_BIT_MASK] ^ parity;	UCSR1A = (1 << TXC1);	UDR1 = pattern;	data >>= BITS_PER_PATTERN_BYTE;	left -= BITS_PER_PATTERN_BYTE;	parity = -((int8_t)pattern < 0);	return left;}/* * Begin sending a new byte. Use when fmtx_send_*() has returned zero. */uint8_t fmtx_send_byte(uint8_t d){	data = d;	left = 8;	return fmtx_send_more();}/* * Synchronize transmitter before reconfiguration */void fmtx_drain(void){	while (!(UCSR1A & (1 << TXC1)))		do_usb_task();}/* * Initialize the USART hardware and set transmission baudrate. * This is mostly the same as SerialSPI_Init(). * Returns the actual baud rate adjusted for underflow. */#define FMTX_UBRRVAL(b) (SERIAL_SPI_UBBRVAL((b) * (8/BITS_PER_PATTERN_BYTE)))#define UBRR_MAX 4095#define FMTX_MIN_BAUD (F_CPU / (2 * (8/BITS_PER_PATTERN_BYTE) * (UBRR_MAX+1UL)))#define FMTX_MAX_BAUD (F_CPU / (2 * (8/BITS_PER_PATTERN_BYTE)))#if FMTX_MIN_BAUD > CAS_BAUDRATE_ABC80# error "UBRR overflows for standard ABC80 baud rate"#endifuint32_t fmtx_real_baudrate(uint32_t baudrate){	if (baudrate < FMTX_MIN_BAUD || baudrate > FMTX_MAX_BAUD)		baudrate = CAS_BAUDRATE_ABC80;	return baudrate;}void fmtx_init_speed(uint32_t baudrate){	uint32_t ubrrval;	ubrrval = FMTX_UBRRVAL(baudrate);	DDRD |= 0x28; /* PD3 = outdata, PD5 = XCK/TXLED */	PORTD = (PORTD & ~0x28) | 0x20 | (parity & 0x08);	UCSR1B = 0;	/* Disable USART */	UCSR1A = 0;	/* Clear error bits */	/*	 * SPI master mode, mode 1, LSB first	 * UCPHA doesn't matter, but have UCPOL=1 to that the clock	 * is 1 when idle and the TXLED is OFF.	 */	UCSR1C = (3 << UMSEL10) | (1 << UDORD1) | (1 << UCPOL1);	/* UBRR must be zero when the transmitter is enabled */	UBRR1  = 0;	/* Enable transmitter, but not receiver */	UCSR1B = (1 << TXEN1);	/* Configure baud rate */	UBRR1  = ubrrval;	/* Output the current idle state of the line */	UDR1   = parity;}
 |