Zeal8bit / Zeal-8-bit-OS

An Operating System for Z80 computers, written in assembly
Apache License 2.0
574 stars 54 forks source link

I2C: How to call OS routines? #40

Open Candid-Moe opened 1 month ago

Candid-Moe commented 1 month ago

How can I call an OS routine like i2c_send_byte from my own Z80 Assembler program?|

Zeal8bit commented 1 month ago

Hello @Candid-Moe !

I haven't made a public API yet for that, but Zeal 8-bit Computer target implements i2c_send, i2c_receive and i2c_send_receive via write, read and ioctl syscalls respectively.

For example, to send bytes to the I2C from an assembly program, you can do:

#define MY_I2C_ADDR                    0x42
#define I2C_SET_DEVICE_ADDR    0
#define I2C_WRITE_READ_OP       1

ld bc, i2c_name
ld h, O_RDWR
OPEN()
; Assumption no error
; Move the opened descriptor in H
ld h, a
; Set the I2C 7-bit address, use IOCTL for that
ld c, I2C_SET_DEVICE_ADDR ; ioctl operation
ld e, I2C_ADDR ; Parameter, D will be ignored in I2C_SET_DEVICE_ADDR operation
IOCTL()

; Write our buffer to the device
; H already contains the I2C driver descriptor
ld de, i2c_buffer
ld bc, 3
WRITE()
 [...]
; Read from the device
; H already contains the I2C driver descriptor
ld de, i2c_buffer
ld bc, 3
READ()
 [...]
; Write-read is more tricky, it needs a structure defined as:
; struct {
;     uint8_t write_buffer_size;
;     uint8_t read_buffer_size;
;     void* write_buffer;
;     void* read_buffer;
; } i2c_transaction_t;
; Define it below
ld c, I2C_WRITE_READ_OP ; ioctl operation
ld de, transaction
; Assumption is made that H already contains the driver descriptor
IOCTL()

; Close the descriptor, in H
CLOSE()
 [...]

; Name of the I2C driver
i2c_name: DEFM "#I2C0"
; Random data to send to the device
i2c_buffer: DEFM 0x10, 0x11, 0x12
; Write-read transaction
transaction:
     DEFB  1, 3  ; Write a single byte, followed by 3 reads
     DEFW  i2c_buffer, i2c_buffer ; Re-use the same buffer for both read and write