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.
96 lines
2.7 KiB
96 lines
2.7 KiB
/** @file ir.c
|
|
@author M. P. Hayes, UCECE
|
|
@date 23 August 2010
|
|
@brief Infrared driver.
|
|
@note This should be compiled with optimisation enabled to make the
|
|
modulation frequency more accurate.
|
|
*/
|
|
#include "system.h"
|
|
#include "delay.h"
|
|
#include "ir.h"
|
|
#include "pio.h"
|
|
|
|
#define IR_MODULATION_PERIOD_US (1e6 / IR_MODULATION_FREQ)
|
|
|
|
#define IR_SET_TWEAK_US 0.2
|
|
#define LOOP_TWEAK_US 0.8
|
|
|
|
|
|
/** Turn IR transmitter LED on. */
|
|
static inline void ir_tx_on (void)
|
|
{
|
|
pio_output_high (IR_TX_HIGH_PIO);
|
|
}
|
|
|
|
|
|
/** Turn IR transmitter LED off. */
|
|
static inline void ir_tx_off (void)
|
|
{
|
|
pio_output_low (IR_TX_HIGH_PIO);
|
|
}
|
|
|
|
|
|
/** Modulate the IR transmitter LED at IR_MODULATION_FREQ.
|
|
@param state is 1 to enable modulation, 0 to disable modulation
|
|
@param count is the number of modulation periods
|
|
@note This returns after @c count modulation periods. */
|
|
void ir_tx_set (uint8_t state, uint16_t count)
|
|
{
|
|
uint16_t i = 0;
|
|
|
|
/* This modulates the IR LED by bit bashing the IR LED PIO.
|
|
Alternatively, we could use the timer0 peripheral for a more
|
|
accurate modulation frequency.
|
|
|
|
The timing could be made more accurate by tweaking the delays
|
|
to compensate for the other instructions. */
|
|
|
|
if (state)
|
|
{
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
ir_tx_on ();
|
|
DELAY_US (IR_MODULATION_PERIOD_US / 2 - IR_SET_TWEAK_US);
|
|
ir_tx_off ();
|
|
DELAY_US (IR_MODULATION_PERIOD_US / 2 - IR_SET_TWEAK_US - LOOP_TWEAK_US);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
DELAY_US (IR_MODULATION_PERIOD_US - LOOP_TWEAK_US);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** Return output state of IR receiver.
|
|
@return IR receiver state (1 = IR modulation detected). */
|
|
uint8_t ir_rx_get (void)
|
|
{
|
|
/* The output of the IR receiver (TSOP6136TR) is inverted. It is
|
|
normally high but goes low when it detects modulated IR light. */
|
|
|
|
return !pio_input_get (IR_RX_PIO);
|
|
}
|
|
|
|
|
|
/** Initialise PIOs for IR transmitter LED and receiver. */
|
|
void ir_init (void)
|
|
{
|
|
/* Configure transmitter PIOs as outputs and ensure IR LED off.
|
|
Note that the IR LED is driven by two PIOs; to turn on the LED
|
|
IR_TX_HIGH_PIO must be high and IR_TX_LOW_PIO must be low.
|
|
IR_TX_HIGH_PIO is also connected to the timer 0 output so
|
|
we can modulate the LED by the timer. IR_TX_LOW_PIO is also
|
|
connected to the UART TXD output so we can drive it from the UART. */
|
|
|
|
pio_config_set (IR_TX_HIGH_PIO, PIO_OUTPUT_LOW);
|
|
pio_config_set (IR_TX_LOW_PIO, PIO_OUTPUT_LOW);
|
|
|
|
/* Configure receiver PIO as input. IR_RX_PIO is also connected to the
|
|
UART RXD input. */
|
|
pio_config_set (IR_RX_PIO, PIO_INPUT);
|
|
}
|