Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to IOIOLib and IOIO firmware to send infrared codes #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions firmware/app_layer_v1/ir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright 2012 Markus Lanthaler <[email protected]>. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied.
*/

#include "Compiler.h"
#include "HardwareProfile.h"
#include "GenericTypeDefs.h"
#include "ir.h"
#include "pins.h"
#include "timer.h"
#include "logging.h"
#include "sync.h"

#define delayMicroseconds(x) \
{ \
unsigned long _dcnt = (x)*((unsigned long)(0.000001/(1.0/GetInstructionClock())/6)); \
while(_dcnt--); \
}

#define IR_BUFFFER_SIZE 256 // ir data buffer size

static WORD ir_buffer[IR_BUFFFER_SIZE] __attribute__((far));
static WORD ir_buffer_length = 0;


//--------------------------------------------------------------------------
void bufferIrData(WORD data) {
if(ir_buffer_length < IR_BUFFFER_SIZE) {
ir_buffer[ir_buffer_length] = data;
ir_buffer_length++;
} else {
log_printf("IR buffer too small! Cleared it");
ir_buffer_length = 0;
}
}


//--------------------------------------------------------------------------
/**
* Send a burst-pair over infrared.
*
* This method sends a burst pair over IR. A burst pair is a on/off
* sequence with the specified duration. As result, this method first
* flashes the IR transmitter LED for "on_length" periods with a
* frequency of (1000 / (2 * pulse_width) kHz) and then it switches the IR
* transmitter LED of for "off_length" periods.
*
* @param pin the pin to which the LED is attached.
* @param pulse_width the pulse width of the carrier (= carrier frequency / 2)
* in microseconds.
* @param on_length the length of the high-signal to sent in number of carrier
* periods.
* @param off_length the length of the low-signal to sent in number of carrier
* periods.
*/
static inline void sendIrBurstPair(int pin, unsigned int pulse_width, WORD on_length, WORD off_length) {
// activate pulse modulated signal
for(; on_length > 0; on_length--)
{
PinSetLat(pin, 1); // set IR pin to HIGH
delayMicroseconds(pulse_width);
PinSetLat(pin, 0); // set IR pin to LOW
delayMicroseconds(pulse_width);
}

// deactivate pulse modulated signal
for(; off_length > 0; off_length--)
{
PinSetLat(pin, 0); // set IR pin to LOW
delayMicroseconds(pulse_width);
PinSetLat(pin, 0); // do it again to get timing right
delayMicroseconds(pulse_width);
}
}


//--------------------------------------------------------------------------
void sendBufferedIrData(int pin) {
if (ir_buffer_length < 4) {
log_printf("IR buffer empty");
ir_buffer_length = 0;
return;
}

unsigned int i = 0;
// TODO If the pulse width is taken from the array I get a 33% duty cycle instead of 50% - fix this
// The current value is tuned to a Pronto value of 006E
unsigned int pronto_frequency = 130; // ir_buffer[1];
unsigned int sequence1_length = ir_buffer[2] * 2;
unsigned int sequence2_length = ir_buffer[3] * 2;

if (ir_buffer_length < 4 + sequence1_length + sequence2_length) {
log_printf("IR data buffer does not contain all required data");
ir_buffer_length = 0;
return;
}

unsigned int pulse_width = (pronto_frequency * 0.241246) / 2;

BYTE prev = SyncInterruptLevel(1);

if(sequence1_length > 0)
{
for(i = 0; i < sequence1_length; i += 2)
{
sendIrBurstPair(pin, pulse_width, ir_buffer[4 + i], ir_buffer[5 + i]);
}
}

if(sequence2_length > 0)
{
for(i = 0; i < sequence2_length; i += 2)
{
sendIrBurstPair(pin, pulse_width, ir_buffer[4 + sequence1_length + i], ir_buffer[5 + sequence1_length + i]);
}
}

ir_buffer_length = 0;

SyncInterruptLevel(prev);
}
50 changes: 50 additions & 0 deletions firmware/app_layer_v1/ir.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2012 Markus Lanthaler <[email protected]>. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied.
*/

#ifndef __IR_H__
#define __IR_H__


/**
* Buffer a burst pair of infrared data before sending it to meet the required
* timing requirements.
*
* @param data the data to buffer.
*/
void bufferIrData(WORD data);

/**
* Send buffered infrared data.
*
* @param pin the pin to which the LED is attached.
*/
void sendBufferedIrData(int pin);


#endif // __IR_H__
2 changes: 2 additions & 0 deletions firmware/app_layer_v1/nbproject/configurations.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<itemPath>sync.h</itemPath>
<itemPath>timers.h</itemPath>
<itemPath>uart.h</itemPath>
<itemPath>ir.h</itemPath>
</logicalFolder>
<logicalFolder name="LibraryFiles"
displayName="Library Files"
Expand Down Expand Up @@ -71,6 +72,7 @@
<itemPath>spi.c</itemPath>
<itemPath>timers.c</itemPath>
<itemPath>uart.c</itemPath>
<itemPath>ir.c</itemPath>
</logicalFolder>
<logicalFolder name="ExternalFiles"
displayName="Important Files"
Expand Down
14 changes: 13 additions & 1 deletion firmware/app_layer_v1/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "uart.h"
#include "spi.h"
#include "i2c.h"
#include "ir.h"
#include "sync.h"
#include "icsp.h"
#include "incap.h"
Expand Down Expand Up @@ -79,7 +80,9 @@ const BYTE incoming_arg_size[MESSAGE_TYPE_LIMIT] = {
sizeof(ICSP_CONFIG_ARGS),
sizeof(INCAP_CONFIG_ARGS),
sizeof(SET_PIN_INCAP_ARGS),
sizeof(SOFT_CLOSE_ARGS)
sizeof(SOFT_CLOSE_ARGS),
sizeof(IR_DATA),
sizeof(IR_SEND_DATA_ARGS)
// BOOKMARK(add_feature): Add sizeof (argument for incoming message).
// Array is indexed by message type enum.
};
Expand Down Expand Up @@ -489,6 +492,15 @@ static BOOL MessageDone() {
state = STATE_CLOSING;
break;

case IR_BUFFER_DATA:
bufferIrData(rx_msg.args.ir_data.data);
break;

case IR_SEND_DATA:
CHECK(rx_msg.args.ir_send_data.pin < NUM_PINS);
sendBufferedIrData(rx_msg.args.ir_send_data.pin);
break;

// BOOKMARK(add_feature): Add incoming message handling to switch clause.
// Call Echo() if the message is to be echoed back.

Expand Down
16 changes: 16 additions & 0 deletions firmware/app_layer_v1/protocol_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,17 @@ typedef struct PACKED {
BYTE enable : 1;
} SET_PIN_UART_ARGS;

// a IR burst pair
typedef struct PACKED {
WORD data;
} IR_DATA;

// ir send data
typedef struct PACKED {
BYTE pin : 6;
BYTE : 2;
} IR_SEND_DATA_ARGS;

// spi report tx status
typedef struct PACKED {
BYTE spi_num : 2;
Expand Down Expand Up @@ -408,6 +419,8 @@ typedef struct PACKED {
INCAP_CONFIG_ARGS incap_config;
SET_PIN_INCAP_ARGS set_pin_incap;
SOFT_CLOSE_ARGS soft_close;
IR_DATA ir_data;
IR_SEND_DATA_ARGS ir_send_data;
// BOOKMARK(add_feature): Add argument struct to the union.
} args;
BYTE __vabuf[64]; // buffer for var args. never access directly!
Expand Down Expand Up @@ -499,6 +512,9 @@ typedef enum {

SOFT_CLOSE = 0x1D,

IR_BUFFER_DATA = 0x1E,
IR_SEND_DATA = 0x1F,

// BOOKMARK(add_feature): Add new message type to enum.
MESSAGE_TYPE_LIMIT
} MESSAGE_TYPE;
Expand Down
13 changes: 12 additions & 1 deletion software/IOIOLib/src/ioio/lib/api/IOIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -693,4 +693,15 @@ public TwiMaster openTwiMaster(int twiNum, Rate rate, boolean smbus)
* method.
*/
public void endBatch() throws ConnectionLostException;
}

/**
*
* @param pin
* Pin number, as labeled on the board.
* @return Interface of the assigned pin.
* @throws ConnectionLostException
* Connection was lost before or during the execution of this
* method.
*/
public IrTransmitter openIrOutput(int pin) throws ConnectionLostException;
}
75 changes: 75 additions & 0 deletions software/IOIOLib/src/ioio/lib/api/IrTransmitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2012 Markus Lanthaler <[email protected]>. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied.
*/
package ioio.lib.api;

import ioio.lib.api.exception.ConnectionLostException;

/**
* A pin used for sending infrared codes.
* <p>
* An infrared transmitter pin can be used to send infrared signals.
* IrTransmitter instances are obtained by calling
* {@link IOIO#openIrOutput(int pin)}.
* <p>
* The infrared code is send by calling {@link #transmitIrCommand(int[]}. The
* data must encoded as
* {@link http://www.remotecentral.com/features/irdisp2.htm Pronto} burst-pair
* stream, i.e., two bytes are combined into one integer and form a burst-pair.
* <p>
* The instance is alive since its creation. If the connection with the IOIO
* drops at any point, the instance transitions to a disconnected state, in
* which every attempt to use the pin (except {@link #close()}) will throw a
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
* instance may no longer be used. Any resources associated with it are freed
* and can be reused.
* <p>
* Typical usage:
*
* <pre>
* IrTransmitter ir = ioio.openIrOutput(10); // IR LED anode on pin 10.
* ir.transmitIrCommand(prontoCode); // send Pronto encoded IR signal.
* ...
* ir.close(); // pin 10 can now be used for something else.
* </pre>
*
* @author Markus Lanthaler <[email protected]>
* @author Andrej Eisfeld <[email protected]>
* @author Sergej Proskurin <[email protected]>
*/
public interface IrTransmitter extends Closeable {
/**
* Transmit a Pronto-encoded IR command.
*
* @param data
* The data to transmit.
* @throws ConnectionLostException
* The connection with the IOIO has been lost.
*/
public void transmitIrCommand(int[] data) throws ConnectionLostException;
}
Loading