You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.2 KiB

/** @file ir_uart.c
@author Michael Hayes
@date 10 December 2004
*/
#include "system.h"
#include "ir_uart.h"
#include "usart1.h"
#include "timer0.h"
#include "pio.h"
#include "delay.h"
/* Return non-zero if there is a character ready to be read. */
bool
ir_uart_read_ready_p (void)
{
return usart1_read_ready_p ();
}
/* Read character from IR_UART. This blocks if nothing
is available to read. */
int8_t
ir_uart_getc (void)
{
return usart1_getc ();
}
/* Return non-zero if a character can be written without blocking. */
bool
ir_uart_write_ready_p (void)
{
return usart1_write_ready_p ();
}
/* Return non-zero if transmitter finished. */
bool
ir_uart_write_finished_p (void)
{
return usart1_write_finished_p ();
}
/** Write character to IR_UART. This blocks until the character can
be written into the transmit buffer. It does not check to see
if there is any echoed character (see ir_uart_putc). */
void
ir_uart_putc_nocheck (char ch)
{
usart1_putc (ch);
}
/** Write character to IR_UART. This blocks until the character is
written. It then checks if data has been received and if so, reads
the data and throws it away on the assumption that it is electrical
or optical echoing. */
void
ir_uart_putc (char ch)
{
/* At 2400 baud with one start bit, 8 data bits, and no parity,
this will take 3.75 ms to transmit. Note, the maximum bit rate
for the IR receiver is 4000 bps. */
usart1_putc (ch);
/* Gobble echoed character. The echoing is due to an electrical
common-path interference problem caused by a poor PCB layout of the
track powering the IR receiver. Unfortunately, it does not always
occur with some combination of UCFK4 boards and laptops. Perhaps
some laptops are more miserly with their current allocation and
some IR LEDs do not draw as much current? So as a workaround
we need to wait until the transmission has finished and then check
if something was immediately received.
Having said all this, it is possible to get an optical reflection
of the transmitted signal. The following code should handle this
as well. */
while (! ir_uart_write_finished_p ())
continue;
/* The IR receiver has a delay of about 150 microseconds. So need
to wait for UART to have received the data and set its receive
complete bit. */
DELAY_US (150);
/* Check is something was inadvertently read. */
if (ir_uart_read_ready_p ())
ir_uart_getc ();
}
/* Write string to IR_UART. */
void
ir_uart_puts (const char *str)
{
usart1_puts (str);
}
/* Initialise ir_uart and set baud rate. */
uint8_t
ir_uart_init (void)
{
usart1_cfg_t usart1_cfg =
{
.baud_divisor = USART1_BAUD_DIVISOR (IR_UART_BAUD_RATE),
.bits = 8
};
/* Need to configure DDR so pin is an output.
The state is controlled by the timer. */
pio_config_set (IR_TX_HIGH_PIO, PIO_OUTPUT_HIGH);
timer0_init ();
timer0_period_set (F_CPU / (IR_MODULATION_FREQ * 2));
timer0_mode_set (TIMER0_MODE_CTC);
timer0_output_set (TIMER0_OUTPUT_B, TIMER0_OUTPUT_MODE_TOGGLE);
timer0_start ();
return usart1_init (&usart1_cfg);
}