Okay, I will try to ask more specific questions. I also saw that a similar
problem was reported here: Maximum TWI transaction size
<https://groups.google.com/forum/#!topic/ioio-users/HvqKBGH7wNE> . This
might be related?
Questions:
*1.* I cannot find the files for for previous versions of the Firmware. I
downloaded all the files contained in the GitHub. I would like to take a
look at the files of Firmware version IOIO0326 to compare them with my
slightly modified versions to see the differences. Especially the i2c.c/.h
and the protocol.c/.h. Is there a way to find such files somewhere else?
*2.* The problem I have seems to be related to latency or drops of bytes
(because of a full buffer?). Which lead to disconnection of the PIC IOIO
and freezing my App. I am able to receive the first few bytes and then
after a few writeRead() the PIC sends
a AppProtocolSendMessageWithVarArgSplit then the Android App
freezes. Obviously, now I get writeRead acknowledges for the correct reads,
when it drops I don't get the
aknowledge. This AppProtocolSendMessageWithVarArgSplit seems to occur
because of a latency problem which provokes a lost of bytes (0 bytes at
beginning and 183 bytes at the end? when I am supposed to have 4 bytes ,
see screenshot attached). Please note that psd_buff_ptr contains the value
I'm reading (in my UART logging) and I am able to see this value appear in
my LogCat sometimes or partly see attached LogCat excerpt.
I tried increasing Interrupt Priority level from 4 to 2, as you did in the
change from V3.x to V5.x of the Firmware. Then my Device seems to bootup
faster because of all my i2c calls which now have higher priority, but my
latency or dropout problem still occurs. As soon as I get the drop and then
reboot my App, my Device also reboots to reconnect with the App. Please
find my versions of i2c and protocol.c attached (based on V3.x), I think
the problem would mainly be there. Again I did compare these files with the
V5.x version and didn't see major changes other than optimization of some
functions like atomic16 and AssignMI2CxIF. The problem occurs no matter
if I use twi.writeRead() or twi.writeReadAsync().
Maybe I need a better explanation of how to use twi.writeRead() and
twi.writeReadAsync()? Also explanation on the use of buffers RX_BUF_SIZE in
i2c.c and DEFINE_STATIC_BYTE_QUEUE in protocol.c could help me? Would it be
useful to clear these buffers after a few reads?
I included an excerpt of the problematic code section of my Android App in
attachment. If I take out the writeRead() call everything is fine since the
i2c would not be used.
*3.* I am starting to think that it could be the reading of the
DSP register that could cause the latency and crash the connection?
According to the 0 bytes received in the logging...What do you think?
I am deeply sorry if all my messages bother you. I am simply doing my best
to find the problem and solve it.
Vincent
Le mardi 31 mars 2015 19:04:51 UTC+2, Ytai a écrit :
>
> I don't see how I can effectively help you when you're running a modified
> version of the firmware that I am not familiar with and are unable to
> demonstrate the the problem originates from the standard codebase (not to
> say that it doesn't).
> You need to debug your code and figure out what's happening. If you get to
> a conclusion that some of the existing code is wrong, I would love to look
> into it. If you have specific question about the code or about how to debug
> I would love to help.
>
> On Tue, Mar 31, 2015 at 9:28 AM, Vincent Nadon <[email protected]
> <javascript:>> wrote:
>
>> *UPDATE*: I have found the problem related to the non responsive calls
>> of twi.readWrite() with my custom firmware (V3.x), this was due to some
>> modifications we did in the i2c.c file commenting all calls of rx_queue.
>> After uncommenting these lines, the Andrdoid App received the read
>> acknowledge (Result...).
>>
>> I still wasn't able to make V5.x *stock *firmware work on my custom
>> platform. As you say I would probably need to try it on a stock IOIO
>> hardware board, but at this time for me it is too complicated (buying a
>> IOIO, trying it, then trying to debug my custom board again) and it would
>> get me further from the problem that I already partly solved.
>>
>> *Now, I have two problems*:
>>
>> 1. After about 24 twi.readWrite() calls, my PIC restarts by itself so
>> I can only do 24 reads whether it is 1 every 100ms or 1 every 1second. In
>> my case I would like to do 22x 10 readings, 1 every 100ms. I had
>> previously
>> decreased DEFINE_STATIC_BYTE_QUEUE to 128 instead of 8192 for the rx to
>> have enough memory space for proper functionnality of my DSPs. I tried to
>> increase it to 2048, but then my audio signals didn't sound right in my
>> DSP
>> and also it didn't solve the problem that after 24 reads the PIC
>> restarts.
>> To me this seems to be some kind of buffer problem, when it gets full it
>> crashes. I guess there could be a way to reset this buffer every few
>> calls,
>> if we find this faulty buffer??
>> 2. I cannot read the response value. I see in my PIC logging that the
>> command to read passes and the correct value is in the buffer in the PIC,
>> but it doesn't get in the Android App...
>>
>>
>> Le vendredi 27 mars 2015 11:22:59 UTC+1, Vincent Nadon a écrit :
>>>
>>> I'm only talking about the Hardware firmware now. I can't even try with
>>> my Android App since my hardware doesn't even boot and therefore doesn't
>>> establish the bluetooth or USB connection. As I said I am using the IOIO
>>> V5.x as plain as I can. I will try again without changing anything at all,
>>> but chances are there might be something that I need to modify that I don't
>>> see.
>>>
>>> As you say it is hard to find the problem since I have custom hardware
>>> and therefore need to modify the Firmware a bit.
>>>
>>>
>>> Le vendredi 27 mars 2015 08:43:31 UTC+1, Ytai a écrit :
>>>>
>>>> There are too many things that can go wrong in your setup: custom IOIO,
>>>> custom forward with changes that are very likely to break stuff and a fair
>>>> amount of complexity in your app.
>>>> I recommend that you start by eliminating some possible causes (e.g.
>>>> test your app on a stock IOIO with stock firmware or run a rigorous test
>>>> on
>>>> your custom hardware/firmware, such as the IOIO torture test.
>>>> Otherwise you'd be wasting our time.
>>>> On Mar 26, 2015 9:30 AM, "Vincent Nadon" <[email protected]> wrote:
>>>>
>>>>>
>>>>> - So I tried the V5.X firmware, as plain vanilla as I could. I
>>>>> have put some call for LEDs to light up during boot process and I
>>>>> connected
>>>>> an Arduino USB2Serial to monitor the logging.
>>>>>
>>>>> As it is, no LEDs light up and I don't see anything in the logging,
>>>>> no "***** Hello from app-layer! *******", nothing... Even my bluetooth
>>>>> dongle doesn't seem to light up anymore.
>>>>>
>>>>>
>>>>>
>>>>> I did configure everything to suit my hardware (PIC24FJ256DA206) and
>>>>> then also changed the pins for my UART according to what I had working in
>>>>> my previous firmware, and changed few pins for LEDs. I also configured
>>>>> the
>>>>> ENABLE_LOGGING in the pic30-gcc preprocessor macros.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> libusb, libconn, libbtstack, libadb, Bootloader and AppLayerV1 all
>>>>> build without errors.
>>>>>
>>>>>
>>>>>
>>>>> - I have also another question, in my previous firmware version I
>>>>> had to set Memory_Model to Large Data, Large code and small scalar. I
>>>>> also
>>>>> had to modify QUEUE_SIZE in protocol.c to 128 (instead of 8192) to fit
>>>>> the
>>>>> code to program my DSPs in the pic memory. Would you have a better
>>>>> suggestion to provide the memory space for DSP code? (I use the pic to
>>>>> program my DSPs at bootup)
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "ioio-users" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>> To post to this group, send email to [email protected].
>>>>> Visit this group at http://groups.google.com/group/ioio-users.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>> --
>> You received this message because you are subscribed to the Google Groups
>> "ioio-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> To post to this group, send email to [email protected]
>> <javascript:>.
>> Visit this group at http://groups.google.com/group/ioio-users.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
--
You received this message because you are subscribed to the Google Groups
"ioio-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/ioio-users.
For more options, visit https://groups.google.com/d/optout.
/*
* Copyright 2011 Ytai Ben-Tsvi. 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 __I2C_H__
#define __I2C_H__
void I2CInit();
void I2CTasks();
// rate is 0:off 1:100KHz, 2:400KHz, 3:1MHz
void I2CConfigMaster(int i2c_num, int rate, int smbus_levels);
int I2CWriteRead(int i2c_num, unsigned int addr, const void* data,
int write_bytes, int read_bytes);
extern unsigned char psdbuff_ptr[4];
#endif // __I2C_H__
/*
* Copyright 2011 Ytai Ben-Tsvi. 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 "protocol.h"
#include <assert.h>
#include <string.h>
#include "libpic30.h"
#include "blapi/version.h"
#include "byte_queue.h"
#include "features.h"
#include "pwm.h"
#include "adc.h"
#include "digital.h"
#include "logging.h"
#include "platform.h"
#include "uart.h"
#include "spi.h"
#include "i2c.h"
#include "sync.h"
#include "icsp.h"
#include "incap.h"
#define CHECK(cond) do { if (!(cond)) { log_printf("Check failed: %s", #cond); return FALSE; }} while(0)
const BYTE incoming_arg_size[MESSAGE_TYPE_LIMIT] = {
sizeof(HARD_RESET_ARGS),
sizeof(SOFT_RESET_ARGS),
sizeof(CHECK_INTERFACE_ARGS),
sizeof(SET_PIN_DIGITAL_OUT_ARGS),
sizeof(SET_DIGITAL_OUT_LEVEL_ARGS),
sizeof(SET_PIN_DIGITAL_IN_ARGS),
sizeof(SET_CHANGE_NOTIFY_ARGS),
sizeof(REGISTER_PERIODIC_DIGITAL_SAMPLING_ARGS),
sizeof(SET_PIN_PWM_ARGS),
sizeof(SET_PWM_DUTY_CYCLE_ARGS),
sizeof(SET_PWM_PERIOD_ARGS),
sizeof(SET_PIN_ANALOG_IN_ARGS),
sizeof(SET_ANALOG_IN_SAMPLING_ARGS),
sizeof(UART_CONFIG_ARGS),
sizeof(UART_DATA_ARGS),
sizeof(SET_PIN_UART_ARGS),
sizeof(SPI_CONFIGURE_MASTER_ARGS),
sizeof(SPI_MASTER_REQUEST_ARGS),
sizeof(SET_PIN_SPI_ARGS),
sizeof(I2C_CONFIGURE_MASTER_ARGS),
sizeof(I2C_WRITE_READ_ARGS),
sizeof(RESERVED_ARGS),
sizeof(ICSP_SIX_ARGS),
sizeof(ICSP_REGOUT_ARGS),
sizeof(ICSP_PROG_ENTER_ARGS),
sizeof(ICSP_PROG_EXIT_ARGS),
sizeof(ICSP_CONFIG_ARGS),
sizeof(INCAP_CONFIG_ARGS),
sizeof(SET_PIN_INCAP_ARGS),
sizeof(SOFT_CLOSE_ARGS)
// BOOKMARK(add_feature): Add sizeof (argument for incoming message).
// Array is indexed by message type enum.
};
const BYTE outgoing_arg_size[MESSAGE_TYPE_LIMIT] = {
sizeof(ESTABLISH_CONNECTION_ARGS),
sizeof(SOFT_RESET_ARGS),
sizeof(CHECK_INTERFACE_RESPONSE_ARGS),
sizeof(RESERVED_ARGS),
sizeof(REPORT_DIGITAL_IN_STATUS_ARGS),
sizeof(RESERVED_ARGS),
sizeof(SET_CHANGE_NOTIFY_ARGS),
sizeof(REGISTER_PERIODIC_DIGITAL_SAMPLING_ARGS),
sizeof(RESERVED_ARGS),
sizeof(RESERVED_ARGS),
sizeof(RESERVED_ARGS),
sizeof(REPORT_ANALOG_IN_STATUS_ARGS),
sizeof(REPORT_ANALOG_IN_FORMAT_ARGS),
sizeof(UART_STATUS_ARGS),
sizeof(UART_DATA_ARGS),
sizeof(UART_REPORT_TX_STATUS_ARGS),
sizeof(SPI_STATUS_ARGS),
sizeof(SPI_DATA_ARGS),
sizeof(SPI_REPORT_TX_STATUS_ARGS),
sizeof(I2C_STATUS_ARGS),
sizeof(I2C_RESULT_ARGS),
sizeof(I2C_REPORT_TX_STATUS_ARGS),
sizeof(ICSP_REPORT_RX_STATUS_ARGS),
sizeof(ICSP_RESULT_ARGS),
sizeof(RESERVED_ARGS),
sizeof(RESERVED_ARGS),
sizeof(ICSP_CONFIG_ARGS),
sizeof(INCAP_STATUS_ARGS),
sizeof(INCAP_REPORT_ARGS),
sizeof(SOFT_CLOSE_ARGS)
// BOOKMARK(add_feature): Add sizeof (argument for outgoing message).
// Array is indexed by message type enum.
};
typedef enum {
STATE_OPEN,
STATE_CLOSING,
STATE_CLOSED
} STATE;
DEFINE_STATIC_BYTE_QUEUE(tx_queue, 128);
static int bytes_out;
static int max_packet;
static STATE state;
typedef enum {
WAIT_TYPE,
WAIT_ARGS,
WAIT_VAR_ARGS
} RX_MESSAGE_STATE;
static INCOMING_MESSAGE rx_msg;
static int rx_buffer_cursor;
static int rx_message_remaining;
static RX_MESSAGE_STATE rx_message_state;
static inline BYTE OutgoingMessageLength(const OUTGOING_MESSAGE* msg) {
return 1 + outgoing_arg_size[msg->type];
}
static inline BYTE IncomingVarArgSize(const INCOMING_MESSAGE* msg) {
switch (msg->type) {
case UART_DATA:
return msg->args.uart_data.size + 1;
case SPI_MASTER_REQUEST:
if (msg->args.spi_master_request.data_size_neq_total) {
return msg->args.spi_master_request.data_size
+ msg->args.spi_master_request.res_size_neq_total;
} else {
return msg->args.spi_master_request.total_size
+ msg->args.spi_master_request.res_size_neq_total;
}
case I2C_WRITE_READ:
return msg->args.i2c_write_read.write_size;
// BOOKMARK(add_feature): Add more cases here if incoming message has variable args.
default:
return 0;
}
}
void AppProtocolInit(CHANNEL_HANDLE h) {
log_printf("AppProtocolInit");
_prog_addressT p;
bytes_out = 0;
rx_buffer_cursor = 0;
rx_message_remaining = 1;
rx_message_state = WAIT_TYPE;
ByteQueueClear(&tx_queue);
max_packet = ConnectionGetMaxPacket(h);
state = STATE_OPEN;
OUTGOING_MESSAGE msg;
msg.type = ESTABLISH_CONNECTION;
msg.args.establish_connection.magic = IOIO_MAGIC;
_init_prog_address(p, hardware_version);
_memcpy_p2d16(msg.args.establish_connection.hw_impl_ver, p, 8);
_init_prog_address(p, bootloader_version);
_memcpy_p2d16(msg.args.establish_connection.bl_impl_ver, p, 8);
memcpy(msg.args.establish_connection.fw_impl_ver, FW_IMPL_VER, 8);
AppProtocolSendMessage(&msg);
}
void AppProtocolSendMessage(const OUTGOING_MESSAGE* msg) {
log_printf("AppProtocolSendMessage");
if (state != STATE_OPEN) return;
BYTE prev = SyncInterruptLevel(1);
ByteQueuePushBuffer(&tx_queue, (const BYTE*) msg, OutgoingMessageLength(msg));
SyncInterruptLevel(prev);
}
void AppProtocolSendMessageWithVarArg(const OUTGOING_MESSAGE* msg, const void* data, int size) {
log_printf("AppProtocolSendMessageWithVarArg");
if (state != STATE_OPEN) return;
BYTE prev = SyncInterruptLevel(1);
ByteQueuePushBuffer(&tx_queue, (const BYTE*) msg, OutgoingMessageLength(msg));
ByteQueuePushBuffer(&tx_queue, data, size);
SyncInterruptLevel(prev);
}
void AppProtocolSendMessageWithVarArgSplit(const OUTGOING_MESSAGE* msg,
const void* data1, int size1,
const void* data2, int size2) {
log_printf("AppProtocolSendMessageWithVarArgSplit");
if (state != STATE_OPEN) return;
BYTE prev = SyncInterruptLevel(1);
ByteQueuePushBuffer(&tx_queue, (const BYTE*) msg, OutgoingMessageLength(msg));
ByteQueuePushBuffer(&tx_queue, data1, size1);
ByteQueuePushBuffer(&tx_queue, data2, size2);
SyncInterruptLevel(prev);
}
void AppProtocolTasks(CHANNEL_HANDLE h) {
//log_printf("AppProtocolTasks");
_LATB8 = 1;
_LATB9 = 0;
if (state == STATE_CLOSED) return;
if (state == STATE_CLOSING && ByteQueueSize(&tx_queue) == 0) {
log_printf("Finished flushing, closing the channel.");
ConnectionCloseChannel(h);
state = STATE_CLOSED;
return;
}
UARTTasks();
SPITasks();
I2CTasks();
ICSPTasks();
if (ConnectionCanSend(h)) {
BYTE prev = SyncInterruptLevel(1);
const BYTE* data;
if (bytes_out) {
ByteQueuePull(&tx_queue, bytes_out);
bytes_out = 0;
}
ByteQueuePeek(&tx_queue, &data, &bytes_out);
if (bytes_out > 0) {
if (bytes_out > max_packet) bytes_out = max_packet;
ConnectionSend(h, data, bytes_out);
}
SyncInterruptLevel(prev);
}
}
static void Echo() {
AppProtocolSendMessage((const OUTGOING_MESSAGE*) &rx_msg);
}
static BOOL MessageDone() {
// TODO: check pin capabilities
switch (rx_msg.type) {
case HARD_RESET:
CHECK(rx_msg.args.hard_reset.magic == IOIO_MAGIC);
HardReset();
break;
case SOFT_RESET:
SoftReset();
Echo();
break;
case SET_PIN_DIGITAL_OUT:
CHECK(rx_msg.args.set_pin_digital_out.pin < NUM_PINS);
SetPinDigitalOut(rx_msg.args.set_pin_digital_out.pin,
rx_msg.args.set_pin_digital_out.value,
rx_msg.args.set_pin_digital_out.open_drain);
break;
case SET_DIGITAL_OUT_LEVEL:
CHECK(rx_msg.args.set_digital_out_level.pin < NUM_PINS);
SetDigitalOutLevel(rx_msg.args.set_digital_out_level.pin,
rx_msg.args.set_digital_out_level.value);
break;
case SET_PIN_DIGITAL_IN:
CHECK(rx_msg.args.set_pin_digital_in.pin < NUM_PINS);
CHECK(rx_msg.args.set_pin_digital_in.pull < 3);
SetPinDigitalIn(rx_msg.args.set_pin_digital_in.pin, rx_msg.args.set_pin_digital_in.pull);
break;
case SET_CHANGE_NOTIFY:
CHECK(rx_msg.args.set_change_notify.pin < NUM_PINS);
if (rx_msg.args.set_change_notify.cn) {
Echo();
}
SetChangeNotify(rx_msg.args.set_change_notify.pin, rx_msg.args.set_change_notify.cn);
if (!rx_msg.args.set_change_notify.cn) {
Echo();
}
break;
case SET_PIN_PWM:
CHECK(rx_msg.args.set_pin_pwm.pin < NUM_PINS);
CHECK(rx_msg.args.set_pin_pwm.pwm_num < NUM_PWM_MODULES);
SetPinPwm(rx_msg.args.set_pin_pwm.pin, rx_msg.args.set_pin_pwm.pwm_num,
rx_msg.args.set_pin_pwm.enable);
break;
case SET_PWM_DUTY_CYCLE:
CHECK(rx_msg.args.set_pwm_duty_cycle.pwm_num < NUM_PWM_MODULES);
SetPwmDutyCycle(rx_msg.args.set_pwm_duty_cycle.pwm_num,
rx_msg.args.set_pwm_duty_cycle.dc,
rx_msg.args.set_pwm_duty_cycle.fraction);
break;
case SET_PWM_PERIOD:
CHECK(rx_msg.args.set_pwm_period.pwm_num < NUM_PWM_MODULES);
SetPwmPeriod(rx_msg.args.set_pwm_period.pwm_num,
rx_msg.args.set_pwm_period.period,
rx_msg.args.set_pwm_period.scale_l
| (rx_msg.args.set_pwm_period.scale_h) << 1);
break;
case SET_PIN_ANALOG_IN:
CHECK(rx_msg.args.set_pin_analog_in.pin < NUM_PINS);
SetPinAnalogIn(rx_msg.args.set_pin_analog_in.pin);
break;
case UART_DATA:
CHECK(rx_msg.args.uart_data.uart_num < NUM_UART_MODULES);
UARTTransmit(rx_msg.args.uart_data.uart_num,
rx_msg.args.uart_data.data,
rx_msg.args.uart_data.size + 1);
break;
case UART_CONFIG:
CHECK(rx_msg.args.uart_config.uart_num < NUM_UART_MODULES);
CHECK(rx_msg.args.uart_config.parity < 3);
UARTConfig(rx_msg.args.uart_config.uart_num,
rx_msg.args.uart_config.rate,
rx_msg.args.uart_config.speed4x,
rx_msg.args.uart_config.two_stop_bits,
rx_msg.args.uart_config.parity);
break;
case SET_PIN_UART:
CHECK(rx_msg.args.set_pin_uart.pin < NUM_PINS);
CHECK(rx_msg.args.set_pin_uart.uart_num < NUM_UART_MODULES);
SetPinUart(rx_msg.args.set_pin_uart.pin,
rx_msg.args.set_pin_uart.uart_num,
rx_msg.args.set_pin_uart.dir,
rx_msg.args.set_pin_uart.enable);
break;
case SPI_MASTER_REQUEST:
CHECK(rx_msg.args.spi_master_request.spi_num < NUM_SPI_MODULES);
CHECK(rx_msg.args.spi_master_request.ss_pin < NUM_PINS);
{
const BYTE total_size = rx_msg.args.spi_master_request.total_size + 1;
const BYTE data_size = rx_msg.args.spi_master_request.data_size_neq_total
? rx_msg.args.spi_master_request.data_size
: total_size;
const BYTE res_size = rx_msg.args.spi_master_request.res_size_neq_total
? rx_msg.args.spi_master_request.vararg[
rx_msg.args.spi_master_request.data_size_neq_total]
: total_size;
const BYTE* const data = &rx_msg.args.spi_master_request.vararg[
rx_msg.args.spi_master_request.data_size_neq_total
+ rx_msg.args.spi_master_request.res_size_neq_total];
SPITransmit(rx_msg.args.spi_master_request.spi_num,
rx_msg.args.spi_master_request.ss_pin,
data,
data_size,
total_size,
total_size - res_size);
}
break;
case SPI_CONFIGURE_MASTER:
CHECK(rx_msg.args.spi_configure_master.spi_num < NUM_SPI_MODULES);
SPIConfigMaster(rx_msg.args.spi_configure_master.spi_num,
rx_msg.args.spi_configure_master.scale,
rx_msg.args.spi_configure_master.div,
rx_msg.args.spi_configure_master.smp_end,
rx_msg.args.spi_configure_master.clk_edge,
rx_msg.args.spi_configure_master.clk_pol);
break;
case SET_PIN_SPI:
CHECK(rx_msg.args.set_pin_spi.mode < 3);
CHECK((!rx_msg.args.set_pin_spi.enable
&& rx_msg.args.set_pin_spi.mode == 1)
|| rx_msg.args.set_pin_spi.pin < NUM_PINS);
CHECK((!rx_msg.args.set_pin_spi.enable
&& rx_msg.args.set_pin_spi.mode != 1)
|| rx_msg.args.set_pin_spi.spi_num < NUM_SPI_MODULES);
SetPinSpi(rx_msg.args.set_pin_spi.pin,
rx_msg.args.set_pin_spi.spi_num,
rx_msg.args.set_pin_spi.mode,
rx_msg.args.set_pin_spi.enable);
break;
case I2C_CONFIGURE_MASTER:
CHECK(rx_msg.args.i2c_configure_master.i2c_num < NUM_I2C_MODULES);
I2CConfigMaster(rx_msg.args.i2c_configure_master.i2c_num,
rx_msg.args.i2c_configure_master.rate,
rx_msg.args.i2c_configure_master.smbus_levels);
break;
case I2C_WRITE_READ:
CHECK(rx_msg.args.i2c_write_read.i2c_num < NUM_I2C_MODULES);
{
unsigned int addr;
if (rx_msg.args.i2c_write_read.ten_bit_addr) {
addr = rx_msg.args.i2c_write_read.addr_lsb;
addr = addr << 8
| ((rx_msg.args.i2c_write_read.addr_msb << 1)
| 0b11110000);
} else {
CHECK(rx_msg.args.i2c_write_read.addr_msb == 0
&& rx_msg.args.i2c_write_read.addr_lsb >> 7 == 0
&& rx_msg.args.i2c_write_read.addr_lsb >> 2 != 0b0011110);
addr = rx_msg.args.i2c_write_read.addr_lsb << 1;
}
I2CWriteRead(rx_msg.args.i2c_write_read.i2c_num,
addr,
rx_msg.args.i2c_write_read.data,
rx_msg.args.i2c_write_read.write_size,
rx_msg.args.i2c_write_read.read_size);
}
break;
case SET_ANALOG_IN_SAMPLING:
CHECK(rx_msg.args.set_analog_pin_sampling.pin < NUM_PINS);
ADCSetScan(rx_msg.args.set_analog_pin_sampling.pin,
rx_msg.args.set_analog_pin_sampling.enable);
break;
case CHECK_INTERFACE:
CheckInterface(rx_msg.args.check_interface.interface_id);
break;
case ICSP_SIX:
ICSPSix(rx_msg.args.icsp_six.inst);
break;
case ICSP_REGOUT:
ICSPRegout();
break;
case ICSP_PROG_ENTER:
ICSPEnter();
break;
case ICSP_PROG_EXIT:
ICSPExit();
break;
case ICSP_CONFIG:
if (rx_msg.args.icsp_config.enable) {
Echo();
}
ICSPConfigure(rx_msg.args.icsp_config.enable);
if (!rx_msg.args.icsp_config.enable) {
Echo();
}
break;
case INCAP_CONFIG:
CHECK(rx_msg.args.incap_config.incap_num < NUM_INCAP_MODULES);
CHECK(!rx_msg.args.incap_config.double_prec
|| 0 == (rx_msg.args.incap_config.incap_num & 0x01));
CHECK(rx_msg.args.incap_config.mode < 6);
CHECK(rx_msg.args.incap_config.clock < 4);
InCapConfig(rx_msg.args.incap_config.incap_num,
rx_msg.args.incap_config.double_prec,
rx_msg.args.incap_config.mode,
rx_msg.args.incap_config.clock);
break;
case SET_PIN_INCAP:
CHECK(rx_msg.args.set_pin_incap.incap_num < NUM_INCAP_MODULES);
CHECK(!rx_msg.args.set_pin_incap.enable
|| rx_msg.args.set_pin_incap.pin < NUM_PINS);
SetPinInCap(rx_msg.args.set_pin_incap.pin,
rx_msg.args.set_pin_incap.incap_num,
rx_msg.args.set_pin_incap.enable);
break;
case SOFT_CLOSE:
log_printf("Soft close requested");
Echo();
state = STATE_CLOSING;
break;
// BOOKMARK(add_feature): Add incoming message handling to switch clause.
// Call Echo() if the message is to be echoed back.
default:
return FALSE;
}
return TRUE;
}
BOOL AppProtocolHandleIncoming(const BYTE* data, UINT32 data_len) {
assert(data);
if (state != STATE_OPEN) {
log_printf("Shouldn't get data after close!");
return FALSE;
}
while (data_len > 0) {
// copy a chunk of data to rx_msg
if (data_len >= rx_message_remaining) {
memcpy(((BYTE *) &rx_msg) + rx_buffer_cursor, data, rx_message_remaining);
data += rx_message_remaining;
data_len -= rx_message_remaining;
rx_buffer_cursor += rx_message_remaining;
rx_message_remaining = 0;
} else {
memcpy(((BYTE *) &rx_msg) + rx_buffer_cursor, data, data_len);
rx_buffer_cursor += data_len;
rx_message_remaining -= data_len;
data_len = 0;
}
// change state
if (rx_message_remaining == 0) {
switch (rx_message_state) {
case WAIT_TYPE:
rx_message_state = WAIT_ARGS;
rx_message_remaining = incoming_arg_size[rx_msg.type];
if (rx_message_remaining) break;
// fall-through on purpose
case WAIT_ARGS:
rx_message_state = WAIT_VAR_ARGS;
rx_message_remaining = IncomingVarArgSize(&rx_msg);
if (rx_message_remaining) break;
// fall-through on purpose
case WAIT_VAR_ARGS:
rx_message_state = WAIT_TYPE;
rx_message_remaining = 1;
rx_buffer_cursor = 0;
if (!MessageDone()) return FALSE;
break;
}
}
}
return TRUE;
}
/*
* Copyright 2011 Ytai Ben-Tsvi. 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.
*/
// IOIO application layer protocol implementation.
//
// Typical usage:
// ADB_CHANNEL h = ...
// AppProtocolInit(h);
// while (1) {
// if (HasIncomingMessage()) {
// AppProtocolHandleIncoming(msg_data, msg_size);
// }
// AppProtocolTasks(h);
// }
//
// TODO: decouple this module from ADB via callback functions for sending data.
#ifndef __PROTOCOL_H__
#define __PROTOCOL_H__
#include "libconn/connection.h"
#include "protocol_defs.h"
// Human-readable string describing app firmware version.
#define FW_IMPL_VER "IOIO0326"
// Initialize this module.
// This function completely resets the module's state and can be called even
// after the module has been initialized in order to reset it.
// h is a channel handle, which will be used for sending outgoing protocol
// messages.
void AppProtocolInit(CHANNEL_HANDLE h);
// Call this function peridically for providing context to this module.
// h is a channel handle, which will be used for sending outgoing protocol
// messages.
void AppProtocolTasks(CHANNEL_HANDLE h);
// Process incoming protocol data.
// data may not be NULL.
BOOL AppProtocolHandleIncoming(const BYTE* data, UINT32 data_len);
// Send a protocol message.
// This is not intended for usage of the bootstrap code that glues the protocol
// to the underlying serial connection layer, but rather for use of modules
// implementing specific features of the protocol which involve producing output
// data.
void AppProtocolSendMessage(const OUTGOING_MESSAGE* msg);
// Send a protocol message with an attachment of variable-size arguments.
// As specified in the protocol specification, some message types may have a
// variable-size argument. This function is only intended for those message
// types.
void AppProtocolSendMessageWithVarArg(const OUTGOING_MESSAGE* msg,
const void* data, int size);
// The same as AppProtocolSendMessageWithVarArg(), but with the argument split
// in two.
void AppProtocolSendMessageWithVarArgSplit(const OUTGOING_MESSAGE* msg,
const void* data1, int size1,
const void* data2, int size2);
#endif // __PROTOCOL_H__
/*
* Copyright 2011 Ytai Ben-Tsvi. 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 "i2c.h"
#include <assert.h>
#include "Compiler.h"
#include "platform.h"
#include "sync.h"
#include "byte_queue.h"
#include "logging.h"
#include "pp_util.h"
#include "protocol.h"
#include "FSIO.h" // SD include
#include<time.h>
#define PACKED __attribute__ ((packed))
#define RX_BUF_SIZE 128 // originally 128, can I increase? K.
#define TX_BUF_SIZE 256 // originally 256, can I change to 1024? Nope, linking memory errors K.
FSFILE *pNewFile3; // for SD K.
char newFile3[]= "write.txt";
int bytesWritten3;
int count = 1;
char *writearg3 = "a";
unsigned char psdbuff_ptr[4] = {0x00, 0x00, 0x00, 0x00};
unsigned int b;
int indice = 0;
int flag = 0;
BOOL flag_read = 0;
int getsize;
typedef enum {
STATE_START,
STATE_ADDR1_WRITE,
STATE_ADDR2_WRITE,
STATE_WRITE_DATA,
STATE_STOP_WRITE_ONLY,
STATE_RESTART,
STATE_ADDR_READ,
STATE_ACK_ADDR_READ,
STATE_READ_DATA,
STATE_ACK_READ_DATA
} MESSAGE_STATE; // Init for Switch statement i2c flow K.
typedef struct PACKED {
union { // MSB = addr1, LSB = addr2 K.
struct {
BYTE addr1; // 8-bit unsigned
BYTE addr2;
};
WORD addr; // 2 BYTE addy K.
};
BYTE write_size; //
BYTE read_size;
} TX_MESSAGE_HEADER; // Contains addy and write/read size K.
typedef struct {
MESSAGE_STATE message_state;
TX_MESSAGE_HEADER cur_tx_header;
int num_tx_since_last_report;
int bytes_remaining;
BYTE_QUEUE rx_queue;
int num_messages_rx_queue;
BYTE_QUEUE tx_queue;
BYTE rx_buffer[RX_BUF_SIZE];
BYTE tx_buffer[TX_BUF_SIZE];
} I2C_STATE; // Main i2c Struct K.
I2C_STATE i2c_states[NUM_I2C_MODULES];
typedef struct {
unsigned int rcv;
unsigned int trn;
unsigned int brg;
unsigned int con; // Control Register p226 Datasheet
unsigned int stat; // Status
unsigned int add;
unsigned int mask; // Slave Mode Address Mask
} I2CREG; // PIC24 Registers, volatile because they can change anytime K.
#define _I2CREG_REF_COMMA(num, dummy) (volatile I2CREG*) &I2C##num##RCV,
volatile I2CREG* i2c_reg[NUM_I2C_MODULES] = {
REPEAT_1B(_I2CREG_REF_COMMA, NUM_I2C_MODULES, 0)
};
DEFINE_REG_SETTERS_1B(NUM_I2C_MODULES, _MI2C, IF)
DEFINE_REG_SETTERS_1B(NUM_I2C_MODULES, _MI2C, IE)
DEFINE_REG_SETTERS_1B(NUM_I2C_MODULES, _MI2C, IP)
static void I2CConfigMasterInternal(int i2c_num, int rate, int smbus_levels, int external); // static because it's local to file K.
void I2CInit() {
log_printf("I2CInit()");
int i;
for (i = 0; i < NUM_I2C_MODULES; ++i) {
Set_MI2CIP[i](4); // interrupt priority 4
I2CConfigMasterInternal(i, 0, 0, 0);
}
}
static inline void I2CSendStatus(int i2c_num, int enabled) {
OUTGOING_MESSAGE msg;
msg.type = I2C_STATUS;
msg.args.i2c_status.i2c_num = i2c_num;
msg.args.i2c_status.enabled = enabled;
AppProtocolSendMessage(&msg);
}
// The function bellow is called only within this file, hence static decleration and 'Internal' keyword. K.
static void I2CConfigMasterInternal(int i2c_num, int rate, int smbus_levels, int external) {
volatile I2CREG* regs = i2c_reg[i2c_num];
I2C_STATE* i2c = i2c_states + i2c_num;
static const unsigned int brg_values[] = { 0x9D, 0x25, 0x0D };
if (external) {
log_printf("I2CConfigMaster(%d, %d, %d)", i2c_num, rate, smbus_levels);
}
Set_MI2CIE[i2c_num](0); // disable interrupt
regs->con = 0x0000; // disable module
Set_MI2CIF[i2c_num](0); // clear interrupt
ByteQueueInit(&i2c->tx_queue, i2c->tx_buffer, TX_BUF_SIZE);
ByteQueueInit(&i2c->rx_queue, i2c->rx_buffer, RX_BUF_SIZE);
i2c->num_tx_since_last_report = 0;
i2c->num_messages_rx_queue = 0;
i2c->message_state = STATE_START;
if (rate) {
if (external) {
I2CSendStatus(i2c_num, 1);
}
i2c->num_tx_since_last_report = TX_BUF_SIZE;
regs->brg = brg_values[rate - 1];
regs->con = (1 << 15) // enable
| ((rate != 2) << 9) // disable slew rate unless 400KHz mode
| (smbus_levels << 8); // use SMBus levels
Set_MI2CIF[i2c_num](1); // signal interrupt
} else {
if (external) {
I2CSendStatus(i2c_num, 0);
}
}
}
// I imagine the function bellow is called from Java, it in-turn calls the proper internal one K.
void I2CConfigMaster(int i2c_num, int rate, int smbus_levels) {
//pNewFile = FSfopen (newFile, "a");
I2CConfigMasterInternal(i2c_num, rate, smbus_levels, 1);
// create the SD file here, everytime a new I2C instance is configured
//char myData[]= "8989";
}
// TODO: Kuba - Print this to Log log_printf
// this is called every time the half of the buffer is transmitted
static void I2CReportTxStatus(int i2c_num) {
int report;
I2C_STATE* i2c = &i2c_states[i2c_num];
BYTE prev = SyncInterruptLevel(4);
report = i2c->num_tx_since_last_report;
i2c->num_tx_since_last_report = 0;
SyncInterruptLevel(prev);
OUTGOING_MESSAGE msg;
msg.type = I2C_REPORT_TX_STATUS;
msg.args.i2c_report_tx_status.i2c_num = i2c_num;
msg.args.i2c_report_tx_status.bytes_to_add = report;
AppProtocolSendMessage(&msg);
}
void I2CTasks() {
int i;
for (i = 0; i < NUM_I2C_MODULES; ++i) {
size_t size1, size2, size;
const BYTE *data1, *data2;
I2C_STATE* i2c = &i2c_states[i];
BYTE_QUEUE* q = &i2c->rx_queue;
BYTE prev;
while (i2c->num_messages_rx_queue) {
OUTGOING_MESSAGE msg;
msg.type = I2C_RESULT;
msg.args.i2c_result.i2c_num = i;
prev = SyncInterruptLevel(4);
msg.args.i2c_result.size = ByteQueuePullByte(q); // Byte lu dans le buffer?? L.
--i2c->num_messages_rx_queue;
SyncInterruptLevel(prev);
log_printf("I2C# %d received %d bytes", i, msg.args.i2c_result.size); //this is how to access the msg you wanted K.
//
// try to send the que to SD
//
if (msg.args.i2c_result.size != 0xFF && msg.args.i2c_result.size > 0) {
ByteQueuePeekMax(q, msg.args.i2c_result.size, &data1, &size1, &data2,
&size2);
size = size1 + size2;
assert(size == msg.args.i2c_result.size);
AppProtocolSendMessageWithVarArgSplit(&msg, data1, size1, data2, size2);
prev = SyncInterruptLevel(4);
ByteQueuePull(q, size);
// psdbuff_ptr = malloc(size * sizeof(int));
// if(psdbuff_ptr == NULL){
// log_printf("allocation mémoire échouée");
// }
// psdbuff_ptr = &q->buf;
//casted as a pointer...
// pNewFile3 = FSfopen (newFile3, writearg3);
// bytesWritten3 = FSfwrite (psdbuff_ptr, 1, 4, pNewFile3);
// log_printf("************* SD TRIED TO WRITE QUEUE: %d *************", bytesWritten3);
// FSfclose(pNewFile3);
// free(psdbuff_ptr);
SyncInterruptLevel(prev);
} else {
AppProtocolSendMessage(&msg);
}
}
if (i2c->num_tx_since_last_report > TX_BUF_SIZE / 2) {
I2CReportTxStatus(i);
}
}
}
int I2CWriteRead(int i2c_num, unsigned int addr, const void* data,
int write_bytes, int read_bytes) {
// if (read_bytes != 0){
// log_printf("SD card : ouverture du fichier");
// pNewFile3 = FSfopen (newFile3, writearg3);
// }
I2C_STATE* i2c = i2c_states + i2c_num;
TX_MESSAGE_HEADER hdr;
BYTE prev;
// 'data' was %p
// log_printf("I2CWriteRead(%d, 0x%x, 0x%p, %d, %d)", i2c_num, addr,
// data, write_bytes, read_bytes);
hdr.addr = addr; // update header with I2C device address K.
hdr.write_size = write_bytes; // # of bytes to write K.
hdr.read_size = read_bytes; // # of bytes to read K.
prev = SyncInterruptLevel(4);
getsize = ByteQueuePushBuffer(&i2c->tx_queue, &hdr, sizeof hdr);
getsize = ByteQueuePushBuffer(&i2c->tx_queue, data, write_bytes);
Set_MI2CIE[i2c_num](1); // enable interrupt K.
SyncInterruptLevel(prev);
return getsize;
}
// Main function were transaction takes place called with interrupt? K.
static void MI2CInterrupt(int i2c_num) {
I2C_STATE* i2c = i2c_states + i2c_num;
volatile I2CREG* reg = i2c_reg[i2c_num];
Set_MI2CIF[i2c_num](0); // clear interrupt
switch (i2c->message_state) {
case STATE_START:
ByteQueuePullToBuffer(&i2c->tx_queue, &i2c->cur_tx_header,
sizeof(TX_MESSAGE_HEADER));
i2c->num_tx_since_last_report += sizeof(TX_MESSAGE_HEADER);
i2c->bytes_remaining = i2c->cur_tx_header.write_size;
reg->con |= 0x0001; // send start bit
// log_printf("I2C Send Start Bit");
if (i2c->bytes_remaining) { // if there are bytes left to transmit then send them otherwise read
i2c->message_state = STATE_ADDR1_WRITE;
} else {
i2c->message_state = STATE_ADDR_READ;
}
break;
case STATE_ADDR1_WRITE: // write ADDR1 and 10-bit case? K.
reg->trn = i2c->cur_tx_header.addr1;
// log_printf("Write ADDR1: 0x%x", i2c->cur_tx_header.addr1);
if (i2c->cur_tx_header.addr1 >> 3 == 0b00011110) {
i2c->message_state = STATE_ADDR2_WRITE; // write the second part of addy K.
} else {
i2c->message_state = STATE_WRITE_DATA;
}
break;
case STATE_ADDR2_WRITE:
if (reg->stat >> 15) goto error; // stat register in PIC probably ACK K.
reg->trn = i2c->cur_tx_header.addr2;
// log_printf("Write ADDR2: %d", i2c->cur_tx_header.addr2);
i2c->message_state = STATE_WRITE_DATA;
break;
case STATE_WRITE_DATA: // Actual Data writing!
if (reg->stat >> 15){
// log_printf("error STATE_WRITE_DATA");
goto error;
}
{
BYTE b = ByteQueuePullByte(&i2c->tx_queue);
reg->trn = b;
// 0x%x for hex
// **************************************************************************************************************
// log_printf("Write DATA: b=0x%x", b);
// **************************************************************************************************************
}
++i2c->num_tx_since_last_report; // increment tx count
if (--i2c->bytes_remaining == 0 ) {
i2c->message_state = i2c->cur_tx_header.read_size // was it write only or restart transmission? K.
? STATE_RESTART
: STATE_STOP_WRITE_ONLY;
}
break;
case STATE_STOP_WRITE_ONLY:
if (reg->stat >> 15) { goto error; }
// log_printf("STATE_STOP_WRITE_ONLY");
goto done;
case STATE_RESTART:
reg->con |= 0x0002; // send restart
// log_printf("STATE_RESTART");
i2c->message_state = STATE_ADDR_READ;
break;
case STATE_ADDR_READ:
// log_printf("STATE_ADDR_READ: 0x%x", i2c->cur_tx_header.addr1);
reg->trn = i2c->cur_tx_header.addr1 | 0x01; // read address, what addy to read K.
i2c->message_state = STATE_ACK_ADDR_READ;
break;
case STATE_ACK_ADDR_READ:
// log_printf("STATE_ACK_ADDR_READ");
if (reg->stat >> 15) goto error;
// from now on, we can no longer fail.
i2c->bytes_remaining = i2c->cur_tx_header.read_size;
ByteQueuePushByte(&i2c->rx_queue, i2c->cur_tx_header.read_size);
reg->con |= 0x0008; // RCEN
i2c->message_state = STATE_READ_DATA;
break;
case STATE_READ_DATA:
ByteQueuePushByte(&i2c->rx_queue, reg->rcv);
// g = ByteQueuePullByte(&i2c->rx_queue);
reg->con &= ~(1 << 5); // reset ack state
reg->con |= (1 << 4)
| (i2c->bytes_remaining == 1) << 5; // nack last byte
i2c->message_state = STATE_ACK_READ_DATA;
BYTE d = reg->rcv; // For Log K.
psdbuff_ptr[indice] = (unsigned char) d; //Stockage des données reçues dans un tableau
//log_printf("psdbuff_ptr[%d] = 0x%x", indice, psdbuff_ptr[indice]);
indice = indice+1;
// log_printf("STATE_READ_DATA b=0x%x indice=%d ", b, indice);
break;
case STATE_ACK_READ_DATA:
if (--i2c->bytes_remaining == 0) {
// clock_t t1,t2;
// float time;
// t1=clock();
log_printf("psdbuff_ptr[0]=0x%x psdbuff_ptr[1]=0x%x psdbuff_ptr[2]=0x%x psdbuff_ptr[3]=0x%x", psdbuff_ptr[0], psdbuff_ptr[1], psdbuff_ptr[2], psdbuff_ptr[3]);
// t2=clock();
// time = (float)(t2-t1)/GetSystemClock();
// log_printf("time=%f", time);
// if(count==1){
// pNewFile3 = FSfopen (newFile3, writearg3);
// }
// bytesWritten3 = FSfwrite ((void *) psdbuff_ptr, 1, 4, pNewFile3);
// log_printf("WRITE TO SD #%d BytesWritten: %d", count, bytesWritten3);
// if(count == 256){
// FSfclose(pNewFile3);
// }
// count++;
indice = 0;
goto done;
} else {
reg->con |= 0x0008; // RCEN
i2c->message_state = STATE_READ_DATA;
}
break;
}
return;
error:
log_printf("I2C error");
// pull remainder of tx message
ByteQueuePull(&i2c->tx_queue, i2c->bytes_remaining);
i2c->num_tx_since_last_report += i2c->bytes_remaining;
ByteQueuePushByte(&i2c->rx_queue, 0xFF);
done:
++i2c->num_messages_rx_queue;
reg->con |= (1 << 2); // send stop bit
i2c->message_state = STATE_START;
Set_MI2CIE[i2c_num](ByteQueueSize(&i2c->tx_queue) > 0);
}
#define DEFINE_INTERRUPT_HANDLERS(i2c_num) \
void __attribute__((__interrupt__, auto_psv)) _MI2C##i2c_num##Interrupt() { \
MI2CInterrupt(i2c_num - 1); \
}
#if NUM_I2C_MODULES > 3
#error Currently only devices with 3 or less I2Cs are supported. Please fix below.
#endif
#if NUM_I2C_MODULES >= 1
DEFINE_INTERRUPT_HANDLERS(1)
#endif
#if NUM_I2C_MODULES >= 2
DEFINE_INTERRUPT_HANDLERS(2)
#endif
#if NUM_I2C_MODULES >= 3
DEFINE_INTERRUPT_HANDLERS(3)
#endif
public class StimDownTimer extends CountDownTimer {
public StimDownTimer(long startTime, long interval) {
super(startTime, interval);
}
@Override
public void onTick(long millisUntilFinished) {
stim_end = 0;
new dataRecCountDownTimer(1400, 200).start();
}
@Override
public void onFinish() {
stim_end = 1;
}
}
public class dataRecCountDownTimer extends CountDownTimer {
public dataRecCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
@Override
public void onTick(long millisUntilFinished) {
try {
read_ack_bool = twi.writeRead(addressDSP3, false, level_RB,
level_RB.length, response,
response.length);
iWrite("Read ACK=" + read_ack_bool);
} catch (ConnectionLostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(read_ack_bool)
{
ByteBuffer buffer = ByteBuffer.wrap(response);
int inInt = buffer.getInt();
String hex_value = Integer.toString(inInt, 16);
iWrite("level=" + hex_value);
}
}
@Override
public void onFinish() {
}
}04-02 18:17:50.443: D/LEVEL_VALUE(28419): 0
04-02 18:17:52.173: D/LEVEL_VALUE(28419): 0
04-02 18:17:53.963: D/LEVEL_VALUE(28419): 0
04-02 18:17:55.763: D/LEVEL_VALUE(28419): 0
04-02 18:17:57.563: D/LEVEL_VALUE(28419): 7fef0000