IIC transfer stop bit?
Pages: 1 2
Tristan M. (2946) 1036 posts |
I’m sure there’s something I’m overlooking. https://www.riscosopen.org/wiki/documentation/show/iic_transfer How does that happen? Does RISCOS_IICOpV generate the stop bit when it reaches the last iic_transfer structure in the list? I can’t find it explicitly mentioned anywhere? I also have to ask, if I want to talk to an IIC device, is this the correct method? or is it intended to be internal OS usage only? |
Jeffrey Lee (213) 6046 posts |
The iic_transfer structure is used by three areas of the OS:
|
Tristan M. (2946) 1036 posts |
You answered everything I needed to know. I appreciate it. I do have one more question. The correct way for me to call OS_IICOp, or rather programs I write is just directly via the OS_IICOp SWI, isn’t it? I haven’t gotten far enough to try using it yet. I’ve been writing a simple C program to talk to the RTC as a test. I’ve got quite a few IIC devices that I’d like to be able to access in RO, rather than using a microcontroller. Although a microcontroller is something I would like to be able to access as a device / devices. |
Jeffrey Lee (213) 6046 posts |
Yes |
Tristan M. (2946) 1036 posts |
Great. Thanks! |
Tristan M. (2946) 1036 posts |
I just want to add something here. I’ve been trying to work out why *IICDevices returns the values that it does when invoked. I realised the reason but I’m not sure how I feel about it. *IICDevices returns the decimal value of an 8 bit address. LSB being the read / write bit in the iic_transfer structure. This is kind of counter intuitive. |
Rick Murray (539) 13393 posts |
Yes, that’s something you’ll get used to with IIC – that the device is a seven bit address and can be represented either as a seven bit value, or as an eight bit over after being shifted to add the read/write bit… |
Tristan M. (2946) 1036 posts |
So it could be looked at as having two different addresses, one for read and one for write, or alternately one address with a read and write register. I’m not sure how I feel about this. Never seen it represented as an eight bit address. |
Rick Murray (539) 13393 posts |
Easy enough to work around…
|
Rick Murray (539) 13393 posts |
Given the old IIC op tries to stuff everything into an eight bit value, I wonder if that’s a literal copy-paste of how the Master MOS (or FileStore, etc) did it? |
Tristan M. (2946) 1036 posts |
Almost immediately I changed the example struct on the Wiki to something like:
I can’t see any functional difference between doing that and using an 8 bit address. |
Rick Murray (539) 13393 posts |
Would it not be better to call “rw” something like “rnw” to emphasise “read not write”? (my original post marked this bit as “write_bit” which nobody spotted, so a reminder might be a good idea ☺) |
Dave Higton (1515) 3404 posts |
You need to be careful. Putting the “not” in the middle can be construed as “read not” or “not write”. I’ve seen that confusion happen. |
Dave Higton (1515) 3404 posts |
The IIC protocol always transfers 8 bit quantities (followed by an ACK bit in the opposite direction), so trying to separate 7 bits of address and 1 bit of read/write would be rather artificial. |
Tristan M. (2946) 1036 posts |
My whole program is a shambles only ever intended for my eyes, but I guess rw is a fairly ambiguous name. My entire goal is to facilitate a read and a write using RISCOS_IICOp. Once I know I can do that, I’ll start a new program. Time for another stupid question to make sure I have things right. With OS_IICOp, the Wiki says R0 is a pointer to a list of IIC_transfer structures. What is the list? is it a datablock, or a list of pointers to the structures? e: Sorry, forgot to reply to Dave. You make a good argument for 8 bits. Is there really any functional difference though between having a read / write bit and having two addresses? |
Rick Murray (539) 13393 posts |
I’ve just looked at some of my old code to bit bash IIC, and it’s now clearer to me. IIC uses a 7 bit address followed by a read/!write bit. But… the data is sent most significant bit first; so all RISC OS will be doing to address the device is outputting the bits starting from the left, ending with the read bit in the right. Neat hack.
Null pointer?
I think so. I mostly still use IIC_Control because although it’s been deprecated and it can’t do multiple buses, it’s dead easy to use. Here’s a device ID, here’s a block of data, and here’s how many bytes to transfer…
As a programmer, you should be able to answer that one… And the answer is absolutely not. So long as the correct device ID is presented to the IIC subsystem at the correct time, nobody nowhere1 is going to care how you arrive at the addresses, whether calculated with a read bit, held as two #define values (I’ll own up, this is what I usually do), or held in Fahrenheit and converted to an integer Celsius value on the fly (possible but not very practical).
Seems like you might want to refresh yourself on pointers (the great feared subject) and understand the difference between passing 1 Before a pedant starts to write a reply, it is a double negative for emphasis, so it doesn’t translate according to the logical interpretation (which would be “nobody nowhere” must mean “everybody everywhere”)… |
Tristan M. (2946) 1036 posts |
Just a quickpost. While rewriting it a little for clarity I found an error I made a few times. OS_IICOp had r1 set to 0 instead of 1. The rest of the instances were fine. So it was trying to transfer 0 blocks on bus 0. It explains what was being printed to screen. I’m writing a second version using IIC_Control because it’s less unwieldy for simple transfers. |
Tristan M. (2946) 1036 posts |
I got the IIC_Control version working, at least I think I did. I went for the 8 bit address model and managed to get read and write reversed. Clever me. When I had them backwards it appears I managed to somehow reset the RTC more or less. It looked sane. I just re-sync’d the RTC and it all looks good. e: |
Tristan M. (2946) 1036 posts |
Bonus IIC_Control version source. I used this page as a reference. I borrowed the BCD conversion functions and the format of the RTC time reading function params but that’s about it.
|
Steve Pampling (1551) 7925 posts |
Could mean “somebody somewhere” I suppose, in which case: |
Rick Murray (539) 13393 posts |
This was begging to be done… ☺
Yes, I write top-down. The other way of doing it just reminds me too much of Pascal… Plus, it makes more sense to start with the outer function ( As for the hellish way I calculate Speaking of drift, its interesting to read the values from the RTC, then try *Time afterwards, in an Obey file: The current RTC time is 13:13:44 (UTC) on 2018/01/28. Sun,28 Jan 2018.14:13:43 Um… 1 Yes, this is my definition of “fun”. Sad, ain’t it? |
Steve Pampling (1551) 7925 posts |
I always thought starting with a programmatic shell (main() in C) was the logical method. You add the detail bits later. |
Rick Murray (539) 13393 posts |
I’m not so happy with this. Looking at the divs and mods, it really looks like something that ought to reduce to some shifts and an AND mask…
Apparently there’s another school of thought that goes that you work on the detail bits first and then figure out how to join them together to make the eventual whole. I’ve crossed out “sensible” because I don’t see how it is possible to write a subfunction before knowing where and how it fits. It’s like starting building a house by painting the plasterboard…before even building the wall… |
Clive Semmens (2335) 3125 posts |
On the other hand, building a house by making walls and roof and floors before you’ve got the bricks and tiles and timber doesn’t make a lot of sense either… 8~) |
Steve Pampling (1551) 7925 posts |
I’d prefer to think of the program shell as the foundations of the house outlining it’s basic shape. |
Pages: 1 2