example of i2c slave device supporting block transfers

Dependencies:   lib_i2c_slave_block

Tested on nucleo board as slave. Use with i2c_master_block_example on raspberry pi as master.

Master I2C write will print on serial terminal 115200. User button will raise an irq; the RPi test program will service the interrupt.

See lib_i2c_slave_block for explanation of code.

main.cpp

Committer:
Wayne Roberts
Date:
2019-02-03
Revision:
3:0288d257446a
Parent:
2:d7e05c75f240

File content as of revision 3:0288d257446a:


#include <mbed.h>
#include "smbus.h"

#define IRQ_OUT_PIN     D6

const int SLAVE_ADDRESS = 0xA0;

RawSerial pc(USBTX, USBRX);

DigitalOut irqOutPin(IRQ_OUT_PIN);
irq_t irq;

DigitalIn button(USER_BUTTON);

uint8_t test_buf[32];

void fill_tx_buf(uint8_t cmd)
{
    static uint8_t cnt = 0;
    unsigned i;

    /* answering (master read) request here */

    switch (cmd) {
        case CMD_TEST3:
        case CMD_TEST12:
        case CMD_TEST32:
            for (i = 0; i < cmd_to_length[cmd]; i++)
                i2c.tx_buf[i] = i + cnt;
            cnt++;
            break;
        case CMD_BUFFER:
            memcpy(i2c.tx_buf, test_buf, sizeof(test_buf));
            break;
        case CMD_IRQ:
            for (i = 0; i < cmd_to_length[CMD_IRQ]; i++)
                i2c.tx_buf[i] = irq.buf[i];

            /* interrupt was (is being) read, clear it */
            irq.fields.flags.button = 0;
            if (irq.buf[0] == 0)
                irqOutPin = 0;

            break;
    }
}

bool cmd_allowed(uint8_t)
{
    /* return false if slave cannot take this cmd now */
    return true;
}

void service_i2c_write(uint8_t cmd, uint8_t len, const uint8_t* req)
{
    uint8_t s8;

    /* taking master write here */

    switch (cmd) {
        case CMD_TEST3:
        case CMD_TEST12:
        case CMD_TEST32:
            for (s8 = 0; s8 < cmd_to_length[cmd]; s8++)
                pc.printf("%02x ", req[s8]);
            pc.printf("\r\n");
            break;
        case CMD_BUFFER:
            memcpy(test_buf, req, sizeof(test_buf));
            break;
        /* failures: */
        case CMD_BUSERR:
            pc.printf("BUSERR%u\r\n", req[0]);
            break;
        case CMD_ARLO:
            pc.printf("ARLO%u\r\n", req[0]); // req[0] tx_cndtr
            break;
        case CMD_TIMEOUT:
            pc.printf("TIMEOUT%u\r\n", req[0]);    // req[0] tx_cndtr
            break;
        default:
            pc.printf("??%02x??\r\n", cmd);
            break;
    } // ..switch (cmd)
}

int main()
{
    int res;
    bool but;
    uint8_t cnt = 0;

    pc.baud(115200);
    pc.printf("\r\nreset\r\n");

    res = smbus_init(I2C_SDA, I2C_SCL, SLAVE_ADDRESS);
    pc.printf("%d = smbus_init()\r\n", res);

    but = button.read();
    while (1) {
        service_i2c();

        if (but != button.read()) {
            irq.fields.cnt = cnt++;
            irq.fields.flags.button = 1;
            irqOutPin = 1;

            but = button.read();
        }

    } // ..while (1)
}