Pi IIC API hardware Support?
Tristan M. (2946) 1039 posts |
I need to ask this to save myself a lot of digging to find an answer. Although the answer is probably “yes”, does the HAL support low and high level SWIs for the IIC bus? Does the HAL support the Pi IIC hardware or does it bit bang pins? Knowing these will save me a lot of time. I started writing an IIC API to go along with my GPIO stuff, but would rather do it via the HAL than bare metal, especially if it does support the rather useful BCM IIC controllers. |
Chris Evans (457) 1614 posts |
AFAIK all hardware platforms supported by RISC OS support in their HAL I2C SWI’s1. One issue to be aware of is that which I2C bus is used varies from platform to platform and that the Original Pi and and the Pi 1 Rev1.2 used different buses. The software we wrote to control our Power Control module is the same (apart from the bus number) For PandaBoard, Pi and IGEPv5 We’ve documented the API of our module here IIRC there is an old deprecated SWI |
Jeffrey Lee (213) 6048 posts |
OS_IICOp is the SWI to use for new code. IIC_Control is the deprecated SWI that Chris mentions. As far as OS_IICOp is concerned, there’s only one IIC bus on the Pi, and the HAL makes sure that it gets mapped to the right physical bus for the board in use. |
Tristan M. (2946) 1039 posts |
I just wanted to say thanks. Sorry I haven’t replied earlier. I haven’t had a chance to try it out yet. Chris. You have touched on a bit of a sticking point for me. You say different systems use different busses. Is there any reliable way to work out what the system is without resorting to tricks? If there is I can’t find it! OS_ReadSysInfo was useless. Even if I could find out the amount of RAM I’d be halfway there. |
Rick Murray (539) 13840 posts |
OS_Memory. Read the number of pages of RAM, the page size, then multiply one by the other. Sometimes a bit of lateral thinking is required. ;-) |
Jeffrey Lee (213) 6048 posts |
Yes, OS_IICOp supports multiple busses. But for the Pi only one bus is supported (the other bus is used by the GPU, I believe). All you need to do is specify bus number zero and the HAL will make sure the correct physical bus is used based on the board type. I think that for all the other modern machines the HAL & OS_IICOp support multiple busses (you can get the number of busses via OS_ReadSysInfo 14). But there’s no standard way of mapping logical busses to physical busses, so some care is needed when writing software that’s intended to work with different machines.
Not at the moment, no. |
Chris Hall (132) 3554 posts |
Is there any reliable way to work out what the system is without resorting to tricks? No, but the utility !ScrHelp (available from !Store) may give you some ideas (it’s written in BASIC) but it is definitely resorting to tricks and will not be future-proof. |
Tristan M. (2946) 1039 posts |
Rick, your solution seems to be good enough to get it working. My code now rather shoddily auto detects 512Mb and 1024MB systems and assigns them to one of two system types. It’ll do for now. I haven’t been able to work on this for a week or two. I’ve lost track. Wasn’t exactly in good health. I knew I wrote some SWI based serial stuff but it took me an hour to find it lol! Apparently I wrote it in Code::Blocks on the PC. |
Rick Murray (539) 13840 posts |
At what level? Hardware bit transitions or SWI interface? To be honest, when in writing code to talk to IIC devices, I mostly still use the IIC_Control SWI as it is a lot simpler to use. Each IIC device has an address (1-126; IIRC 0 and 127 are special). Usually the address is fixed in hardware but there may be a link or two to alter the address slightly to permit two of the same device on the same bus. Take the address and shift it one place to the left. Bit zero is then used as a flag to specify a read or write operation. That’s R0. R1 is a pointer to a buffer. R2 is how many bytes to send/receive. The apparent drawback of the older IIC SWI is that every IIC transaction is self contained and atonic. That is to say, at protocol level, reading a register is START, device address, write register number, STOP (end of first SWI) START, device address, read register contents, STOP (end of second SWI). The IIC bus can do it in one transaction by omitting the first STOP and just repeating START to switch transfer direction. So the newer SWI can be more optimised. To a degree, many devices can mitigate this by having automatic register increment, for example when reading frames of teletext I would set the start address and then just read the entire buffer in one SWI call. With each byte read, the internal address would +1 so there was no need to change the address manually in order to read the contents. A datasheet for your IIC device will tell you more, but it’d be unusual if this was not the case. |
Chris Hall (132) 3554 posts |
Some example code to drive a 16×2 display:
|