tabemann / zeptoforth

A not-so-small Forth for Cortex-M
MIT License
177 stars 15 forks source link

Useage example for I2C. #140

Open 592969 opened 1 week ago

592969 commented 1 week ago

Having a lot of fun playing around with zeptoforth but I am stuck on this issue.

I have looked at the I2C examples in the "test" folder but it is not clear how to read or write a register on a device. What I am trying to do is set a RP2040 up as the master and read and write registers from a slave device. Here is my init code to set it up and this works.

16 constant recv-buffer-size                                    
recv-buffer-size buffer: recv-buffer                             
i2c import                                                      
0 master-i2c                                                    
0 7-bit-i2c-addr                                                
$1F 0 i2c-target-addr!                                          
0 enable-i2c                                                    
0 0 i2c-pin                                                     
0 1 i2c-pin  

I know I need to use ">spi" and "spi>" but it is not clear how to send the address to read or write and how it will be returned.

tabemann commented 1 week ago

On Wed, Sep 4, 2024 at 10:34 AM 592969 @.***> wrote:

Having a lot of fun playing around with zeptoforth but I am stuck on this issue.

I have looked at the I2C examples in the "test" folder but it is not clear how to read or write a register on a device. What I am trying to do is set a RP2040 up as the master and read and write registers from a slave device. Here is my init code to set it up and this works.

16 constant recv-buffer-size recv-buffer-size buffer: recv-buffer i2c import 0 master-i2c 0 7-bit-i2c-addr $1F 0 i2c-target-addr! 0 enable-i2c 0 0 i2c-pin 0 1 i2c-pin

I know I need to use ">spi" and "spi>" but it is not clear how to send the address to read or write and how it will be returned.

SPI and SPI> are for interacting with SPI devices, not I2C devices, I should note.

About reading and writing register addresses on I2C peripherals, that is a matter of how the I2C peripheral works, not the I2C peripheral; zeptoforth itself does not know about this.

However, in the common case you are probably looking at something like this:

For writing,

my-subaddr-reg-buffer my-subaddr-len my-i2c-peripheral >i2c-restart drop my-data-buffer my-data-len my-i2c-peripheral >i2c-stop drop

These two steps can be combined if you write the subaddress and the data to write into a single buffer and send that with >i2c-restart-stop .

For reading,

my-subaddr-reg-buffer my-subaddr-len my-i2c-peripheral >i2c-restart drop my-data-buffer my-data-len my-i2c-peripheral i2c-restart-stop> { my-real-data-len }

In your case my-data-buffer would be recv-buffer and my-data-len would be 16.

Hope this helps,

Travis

592969 commented 1 week ago

This makes more sense. My code is still not working but I think I need to understand buffers a little more. Is there some documentation on this?

I have looked at the forth source code for buffers and don't understand how they work. Is this based on another forth that I can look at documentation on?

i2c import

16 constant recv-buffer-size                                    
recv-buffer-size buffer: recv-buffer                             

1 constant send-buffer-size
send-buffer-size buffer: send-buffer

16 constant real-buffer-size
real-buffer-size buffer: real-buffer

i2c import                                                      
0 master-i2c                                                    
0 7-bit-i2c-addr                                                
$1F 0 i2c-target-addr!                                          
0 enable-i2c                                                    
0 0 i2c-pin                                                     
0 1 i2c-pin  

$04 send-buffer !

send-buffer send-buffer-size 0 >i2c-restart drop
recv-buffer recv-buffer-size 0 i2c-restart-stop> 

recv-buffer @ .
tabemann commented 1 week ago

On Wed, Sep 4, 2024 at 1:08 PM 592969 @.***> wrote:

This makes more sense. My code is still not working but I think I need to understand buffers a little more. Is there some documentation on this?

BUFFER: ( bytes "name" -- ) is standard ANS Forth (even though a lot of zeptoforth is not ANS Forth). When compiling to RAM it allots a cell-aligned buffer in RAM of the given size in bytes whose base address is pushed by executing the word defined with the given name which can be used immediately. When compiling to flash it reserves space for a cell-aligned buffer in RAM of the given size in bytes whose base address is pushed by executing the word defined with the given name that will become available after rebooting (note that using it prior to rebooting will result in undefined behavior, likely a crash).

I have looked at the forth source code for buffers and don't understand how they work. Is this based on another forth that I can look at documentation on?

The behavior when compiling to RAM is consistent with https://forth-standard.org/standard/core/BUFFERColon . The behavior when compiling to flash is not ANS Forth, as it is particular to the needs imposed by zeptoforth's being able to compile to flash.

i2c import

16 constant recv-buffer-size recv-buffer-size buffer: recv-buffer

1 constant send-buffer-size send-buffer-size buffer: send-buffer

16 constant real-buffer-size real-buffer-size buffer: real-buffer

i2c import 0 master-i2c 0 7-bit-i2c-addr $1F 0 i2c-target-addr! 0 enable-i2c 0 0 i2c-pin 0 1 i2c-pin

$04 send-buffer !

send-buffer send-buffer-size 0 >i2c-restart drop recv-buffer recv-buffer-size 0 i2c-restart-stop>

recv-buffer @ .

The only issues I see with your code offhand is that you are not dropping or doing something with the byte count received from I2C-RESTART-STOP> , but in this case it should just leave garbage on the stack and not impact what you are doing here, and you are importing I2C twice, which is unnecessary.

Travis

Message ID: @.***>

tabemann commented 1 week ago

By the way, what device are you attempting to communicate with (so I can take a look at its datasheet to see if there is anything weird about it)?

Thanks,

Travis

Message ID: @.***>

592969 commented 1 week ago

I am now seeing the data come back from reading 0x04 and it goes up when I press a key. Trying to parse out how to display / use the data.

https://github.com/solderparty/bbq10kbd_i2c_sw

tabemann commented 1 week ago

On Wed, Sep 4, 2024 at 2:23 PM 592969 @.***> wrote:

I am now seeing the data come back from reading 0x04 and it goes up when I press a key. Trying to parse out how to display / use the data.

https://github.com/solderparty/bbq10kbd_i2c_sw

Sounds like you have made progress -- you would not be getting this behavior if the I2C interface was broken.

Travis