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

Arduino Wrapper - Need a little more clarity on usage #2

Open
gismofx opened this issue Feb 25, 2014 · 6 comments
Open

Arduino Wrapper - Need a little more clarity on usage #2

gismofx opened this issue Feb 25, 2014 · 6 comments

Comments

@gismofx
Copy link

gismofx commented Feb 25, 2014

Hey Erik,

I'm in the process of writing a wrapper for your updated library for Arduino and with the ATtiny Tiny Cores. Anyway, I've got something primitive actually working with your library, but I'm looking for more clarification on implementation so I can better experiment and document the wrapper code I'm making. From what I've incovered, your code seems much simpler in terms of implementation which I like.

Regarding clarification:
For instance:
calling usi_twi_slave(I2C address, use_sleep,*data_callback, *idle_callback);
this Initializes the TWI. That seems like that's the only thing needed to get this code running.

Usage of data_callback((uint8_t input_buffer_length, const uint8_t *input_buffer,
uint8_t *output_buffer_length, uint8_t *output_buffer);)

Things I want to clarify:

  1. The *data_callback function that I create should test the buffers to determine if it's a read or write transaction and then set the inputs accordingly. correct? Are the length parameters 0 initialized or 1 initialized? For example, in my demo, I want to send two bytes, so when my master reads the device, I need to set the output buffer length = 2 and then create
    dataOut[2] = {b1,b2};
    output_buffer=dataOut;
  2. *idle_callback - Only called when SLEEP is disabled? Idle callback is called after every stop condition. What's it's purpose? Or how is it useful?
  3. use_sleep seems like a boolean, but you use uint8_t? Any reason? Consistency 0 or 1 (false/true)
    What happens when sleep is enabled and when it's disabled? Other effects of the I2C.
    I have only used 0 in my testing.

Just in case, If you're not familiar with arduino..There are two main blocks that are needed so it compiles correctly.

void setup(){}//This is where you initialize things. Only runs once

and

void loop(){} //This code loops

--So Implementing your code in arduino would look something like this:--

void setup()
{
usi_twi_slave(a,b,callback,idle);
}

void loop()
{
//do nothing or do something
}

static void twi_callback(byte input_buffer_length,
const byte *input_buffer,
byte *output_buffer_length,
byte *output_buffer)
{
//do stuff here prepare data to send out or process incoming data.
}

void idle_callback()
{
//idle task?
}

Thanks for all your help and I'm happy to further clarify my questions if needed.

@eriksl
Copy link
Owner

eriksl commented Feb 26, 2014

I'm in the process of writing a wrapper for your updated library for
Arduino and with the ATtiny Tiny Cores.

Cool!

this Initializes the TWI. That seems like that's the only thing needed
to get this code running.

Yep!

Usage of data_callback((uint8_t input_buffer_length, const uint8_t
*input_buffer, uint8_t *output_buffer_length, uint8_t *output_buffer);)

Things I want to clarify:

  1. The *data_callback function that I create should test the buffers to
    determine if it's a read or write transaction and then set the inputs
    accordingly. correct?

No.

The data callback is called when there is data available to the application.

The first function does not only initialize twi, it also takes over
control, until data is received, which is handed to the application via
the data callback.

Are the length parameters 0 initialized or 1 initialized?

It's C, so arrays and lengths are always zero-based.

*idle_callback - Only called when SLEEP is disabled? Idle callback
is called after every stop condition. What's it's purpose? Or how is
it useful?

That's incorrect. The idle_callback is called frequently when sleep is
disabled and it's called less frequently when sleep is enabled. Please
keep in mind the cpu goes out of sleep for various reasons, e.g. any
interrupts, including the START condition interrupt.

use_sleep seems like a boolean, but you use uint8_t? Any reason?
Consistency 0 or 1 (false/true)

Yes it's a bool, but there is no sense in using a bool, because an
uint8_t is the smallest unit that can be passed. If you use a bool,
there is a risk it's expanded to be an "int" and and "int" is 16 bits on
AVR. Better use uint*_t types.

What happens when sleep is enabled and when it's disabled? Other effects of the I2C.
I have only used 0 in my testing.

When sleep is on, the cpu uses much less energy, but it may miss a STOP
condition from another device, because USI doesn't have a STOP condition
interrupt. OTOH I've been running them in "sleep" mode for two years
now, no problem in practise. If you see strange things, first thing to
try is to disable sleep mode.

Just in case, If you're not familiar with arduino..There are two main
blocks that are needed so it compiles correctly.

I am not familiar with Arduino indeed, and I am not planning to change
that ;-)

@gismofx
Copy link
Author

gismofx commented Feb 27, 2014

Thanks for writing me back! You've answered a lot! For now, what I have working is buggy at best.

I still really don't understand the *idle_callback usage. When would I use it? How is it used? Any simple example?

Again, touching back on *data_callback:
When some transaction is initiated with this device, data_callback is executed.
-if data is received(master sends data) then:
input_buffer_length = number of bytes received
const *input_buffer, = data byte(s) (is an array of bytes
(then the code can do something with this information)

-if data is being requested(master requests data/ master reads), the program must then define the following in the code:
*output_buffer_length, (Size of output buffer array- must be greater than or equal to 1 ( >= 1)
*output_buffer = array of bytes to be sent back to master <- if true, I am getting some errors setting this to an array in my callback.

Maybe you have a simple example of data_callback as well? something the sends and receives 2 bytes.

This is funny behavior, but currently I can detect the detect the device on the bus, but it hangs when I attempt to read data 1 byte of data.If I unplug the ATTiny and plug it back it back in during a read request, it will return the byte. The returned byte is either 0 or the correct value.

btw, I'm studying usitwislave.c around line 242 //process read request from master

Thanks!

@eriksl
Copy link
Owner

eriksl commented Mar 2, 2014

I still really don't understand the *idle_callback usage. When would I
use it? How is it used? Any simple example?

I am using to reset the watchdog and also make led blink, so you can see
it's alive. Nothing really more useful I think.

Currently I can detect the detect the device on the bus, but it hangs
when I attempt to read data 1 byte of data. Sometimes if I unplug the
ATTiny and plug it back it back in during a read request, it will return
a byte.

You might want to have a look here: http://github.com/eriksl/attiny861_1

Also have all conditions been met to be able to communicate i2c at all:

  • clock frequency at least 8 MHz, I found doubling the speed to 16 Mhz
    works better (with the PLL) or use a crystal;
  • are your pullups correct, I'd rather not use the internal pullups,
    they're too weak

@gismofx
Copy link
Author

gismofx commented Mar 3, 2014

regarding hardware setup: Using external pull-ups and that are correctly sized and I'm running at 8mhz internal, but calibrated.

I'm reading through your code main.c here:

static void process_input(uint8_t if_input_buffer_length, const uint8_t *if_input_buffer,
uint8_t *if_output_buffer_length, uint8_t *if_output_buffer)

If I have any questions, I'll post back. Thanks!

@eriksl
Copy link
Owner

eriksl commented Mar 3, 2014

regarding hardware setup: Using external pull-ups and that are correctly
sized and I'm running at 8mhz internal, but calibrated.

Okay. The clock doesn't need to be calibrated though, it's not even
required to be very precise. That's the beauty of i2c (and spi) as well,
it's completely asynchronous, using the separate clock line.

I'm reading through your code here:

static void process_input(uint8_t if_input_buffer_length, const uint8_t *if_input_buffer,
uint8_t *if_output_buffer_length, uint8_t *if_output_buffer)

And what is exactly your question?

@gismofx
Copy link
Author

gismofx commented Mar 3, 2014

Thanks for the quick reply. I'm actually reading your code now. When I'm finished reading, I'll post my questions(s).

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants