Beispiel #1
0
void spi_format(spi_t *obj_in, int bits, int mode, int slave)
{
    spi_obj_t *obj = OBJ_P(obj_in);
    cy_en_scb_spi_mode_t new_mode = slave? CY_SCB_SPI_SLAVE : CY_SCB_SPI_MASTER;
    if ((bits < 4) || (bits > 16)) return;
    Cy_SCB_SPI_Disable(obj->base, &obj->context);
    obj->data_bits = bits;
    obj->clk_mode = (cy_en_scb_spi_sclk_mode_t)(mode & 0x3);
    if (obj->ms_mode != new_mode) {
        obj->ms_mode = new_mode;
        spi_init_pins(obj);
    }
    spi_init_peripheral(obj);
}
Beispiel #2
0
void i2c_transfer_asynch(i2c_t *obj_in,
                         const void *tx,
                         size_t tx_length,
                         void *rx, size_t rx_length,
                         uint32_t address,
                         uint32_t stop,
                         uint32_t handler,
                         uint32_t event,
                         DMAUsage hint)
{
    i2c_obj_t *obj = OBJ_P(obj_in);

    (void)hint; // At the moment we do not support DMA transfers, so this parameter gets ignored.

    if (obj->pending != PENDING_NONE) {
        return;
    }

    obj->rx_config.slaveAddress = address >> 1;
    obj->tx_config.slaveAddress = address >> 1;
    obj->events = event;
    obj->handler = handler;
    if (i2c_irq_setup_channel(obj) < 0) {
        return;
    }

    obj->rx_config.buffer = rx;
    obj->rx_config.bufferSize = rx_length;
    obj->rx_config.xferPending = !stop;

    obj->tx_config.buffer = (void *)tx;
    obj->tx_config.bufferSize = tx_length;
    obj->tx_config.xferPending = rx_length || !stop;

    if (tx_length) {
        // Write first, then read, or write only.
        if (rx_length > 0) {
            obj->pending = PENDING_TX_RX;
        } else {
            obj->pending = PENDING_TX;
        }
        Cy_SCB_I2C_MasterWrite(obj->base, &obj->tx_config, &obj->context);
    } else if (rx_length) {
        // Read transaction;
        obj->pending = PENDING_RX;
        Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
    }
}
Beispiel #3
0
int  spi_master_write(spi_t *obj_in, int value)
{
    spi_obj_t *obj = OBJ_P(obj_in);

    if (obj->ms_mode == CY_SCB_SPI_MASTER) {
        while (spi_busy(obj_in)) {
            // wait for the device to become ready
        }
        Cy_SCB_SPI_Write(obj->base, value);
        while (!Cy_SCB_SPI_IsTxComplete(obj->base)) {
            // wait for the transmission to complete
        }
        return Cy_SCB_SPI_Read(obj->base);
    } else {
        return (int)CY_SCB_SPI_RX_NO_DATA;
    }
}
Beispiel #4
0
int i2c_byte_read(i2c_t *obj_in, int last)
{
    i2c_obj_t *obj = OBJ_P(obj_in);
    uint8_t tmp_byte = 0;
    cy_en_scb_i2c_command_t ack = last ? CY_SCB_I2C_NAK : CY_SCB_I2C_ACK;

    /* i2c_start and i2c_byte_write was called. Update state to receive data */
    if (CY_SCB_I2C_MASTER_TX == obj->context.state) {
        obj->context.state = CY_SCB_I2C_MASTER_RX0;
    }

    cy_en_scb_i2c_status_t status = Cy_SCB_I2C_MasterReadByte(obj->base, ack, &tmp_byte, obj->timeout, &obj->context);

    if (status == CY_SCB_I2C_SUCCESS) {
        return tmp_byte;
    } else {
        return (-1);
    }
}
Beispiel #5
0
int i2c_read(i2c_t *obj_in, int address, char *data, int length, int stop)
{
    cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS;
    i2c_obj_t *obj = OBJ_P(obj_in);
    cy_en_scb_i2c_command_t ack = CY_SCB_I2C_ACK;
    int byte_count = 0;
    address >>= 1;

    // Start transaction, send address.
    if (obj->context.state == CY_SCB_I2C_IDLE) {
        status = Cy_SCB_I2C_MasterSendStart(obj->base, address, CY_SCB_I2C_READ_XFER, obj->timeout, &obj->context);
    }
    if (status == CY_SCB_I2C_SUCCESS) {
        while (length > 0) {
            if (length == 1) {
                ack = CY_SCB_I2C_NAK;
            }
            status = Cy_SCB_I2C_MasterReadByte(obj->base, ack, (uint8_t *)data, obj->timeout, &obj->context);
            if (status != CY_SCB_I2C_SUCCESS) {
                break;
            }
            ++byte_count;
            --length;
            ++data;
        }
        // SCB in I2C mode is very time sensitive. In practice we have to request STOP after
        // each block, otherwise it may break the transmission.
        Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
    }

    if (status != CY_SCB_I2C_SUCCESS) {
        Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
        byte_count = i2c_convert_status(status);
    }

    return byte_count;
}
Beispiel #6
0
int i2c_byte_write(i2c_t *obj_in, int data)
{
    i2c_obj_t *obj = OBJ_P(obj_in);

    /* i2c_start was called update state to receive data */
    if (CY_SCB_I2C_MASTER_ADDR == obj->context.state) {
        obj->context.state = CY_SCB_I2C_MASTER_TX;
    }

    cy_en_scb_i2c_status_t status = Cy_SCB_I2C_MasterWriteByte(obj->base, (uint8_t)data, obj->timeout, &obj->context);

    switch (status) {
        case CY_SCB_I2C_MASTER_MANUAL_TIMEOUT:
            return 2;
        case CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK:
        case CY_SCB_I2C_MASTER_MANUAL_NAK:
            return 0;
        case CY_SCB_I2C_SUCCESS:
            return 1;
        default:
            /* Error has occurred */
            return (-1);
    }
}
Beispiel #7
0
static rc_t CC ReportObj(const ReportFuncs *f, uint32_t indent,
    const char *object, bool *wasDbOrTableSet)
{
    Report* self = NULL;
    const char* fullpath = NULL;
    const KDatabase* kdb = NULL;
    const KTable* ktbl = NULL;
    const VDatabase* db = NULL;
    KPathType type = kptNotFound;
    KPathType file_type = kptNotFound;
    bool alias = false;
    uint64_t size = 0;
    bool size_unknown = true;

    rc_t rc = ReportGet(&self);
    assert(self);

    if (wasDbOrTableSet != NULL) {
        *wasDbOrTableSet = self->db != NULL || self->table != NULL;
        return 0;
    }

    if (self->db != NULL) {
        type = kptDatabase;
        db = self->db;
    }
    else if (self->table != NULL) {
        rc_t rc2 = VTableOpenParentRead(self->table, &db);
        if (rc2)
        {
            if (rc == 0)
            {
                rc = rc2;
            }
        }
        else if (!db)
        {
            type = kptTable;
            rc2 = VTableGetKTableRead(self->table, &ktbl);
            if (rc2)
            {
                if (rc == 0)
                {
                    rc = rc2;
                }
            }
            else
            {
                rc2 = KTableGetPath(ktbl, &fullpath);
            }
        }
    }

    if (db) {
        rc_t rc2 = VDatabaseOpenKDatabaseRead(db, &kdb);
        type = kptDatabase;
        if (rc2) {
            if (rc == 0)
            {   rc = rc2; }
        }
        else {
            rc2 = KDatabaseGetPath(kdb, &fullpath);
            if (rc2) {
                if (rc == 0)
                {   rc = rc2; }
            }
        }
    }

    if (fullpath) {
        KDirectory* dir = NULL;
        rc_t rc2 = KDirectoryNativeDir(&dir);
        if (rc2) {
            if (rc == 0)
            {   rc = rc2; }
        }
        else {
            file_type = KDirectoryPathType(dir, "%s", fullpath);
            alias = file_type & kptAlias;
            file_type &= ~kptAlias;
            if (file_type == kptFile) {
                rc2 = KDirectoryFileSize(dir, &size, "%s", fullpath);
                if (rc2) {
                    if (rc == 0)
                    {   rc = rc2; }
                }
                else {  size_unknown = false; }
            }
        }
        RELEASE(KDirectory, dir);
    }

    if (object || type != kptNotFound) {
        const char* path
            = fullpath ? fullpath : object ? object : "not set";
        const char* stype = type == kptTable ? "table" : 
            type == kptDatabase ? "database" : "unknown";
        const char* sfile_type = file_type == kptFile ? "archive" : 
            file_type == kptDir ? "dir" : "unexpected";

        if (fullpath && !size_unknown) {
            if (alias)
            { OBJ_P_S_A(indent, path, stype, sfile_type, size); }
            else
            { OBJ_P_S  (indent, path, stype, sfile_type, size); }
        }
        else if (fullpath && size_unknown) {
            if (alias)
            { OBJ_P_A  (indent, path, stype, sfile_type); }
            else
            { OBJ_P    (indent, path, stype, sfile_type); }
        }
        else
        {     OBJ      (indent, path, stype); }

        if (!db)
        {   db = self->db; }

        if (db) {
            rc_t rc2 = ReportDepend(f, indent + 1, db);
            if (rc == 0)
            {   rc = rc2; }
        }
        if (file_type == kptDir) {
            rc_t rc2 = ReportDir(f, indent + 1, ktbl);
            if (rc == 0)
            {   rc = rc2; }
        }

        reportClose(indent, "Object");
    }

    if (db != self->db)
    {   RELEASE(VDatabase, db); }
    RELEASE(KTable, ktbl);
    RELEASE(KDatabase, kdb);

    return rc;
}
Beispiel #8
0
uint8_t i2c_active(i2c_t *obj_in)
{
    i2c_obj_t *obj = OBJ_P(obj_in);
    return (obj->pending != PENDING_NONE);
}
Beispiel #9
0
void i2c_init(i2c_t *obj_in, PinName sda, PinName scl)
{
    i2c_obj_t *obj = OBJ_P(obj_in);

    uint32_t i2c = pinmap_peripheral(sda, PinMap_I2C_SDA);
    i2c = pinmap_merge(i2c, pinmap_peripheral(scl, PinMap_I2C_SCL));

    if (i2c != (uint32_t) NC) {
        /* Initialize configuration */
        obj->base    = (CySCB_Type *) i2c;
        obj->i2c_id  = ((I2CName) i2c - I2C_0) / (I2C_1 - I2C_0);
        obj->clock   = CY_PIN_CLOCK(pinmap_function(scl, PinMap_I2C_SCL));
        obj->divider = I2C_INVALID_DIVIDER;
        obj->already_reserved = (0 != cy_reserve_scb(obj->i2c_id));
        obj->pin_sda = sda;
        obj->pin_scl = scl;

        obj->mode    = CY_SCB_I2C_MASTER;
        obj->timeout = I2C_DEFAULT_TIMEOUT;

#if DEVICE_I2C_ASYNCH
        obj->irqn    = unconnected_IRQn;
        obj->pending = PENDING_NONE;
        obj->events  = 0;
#endif /* DEVICE_I2C_ASYNCH */

        /* Check if resource severed */
        if (obj->already_reserved) {

            /* SCB pins and clocks are connected */

            /* Disable block and get it into the default state */
            Cy_SCB_I2C_Disable(obj->base, &obj->context);
            Cy_SCB_I2C_DeInit(obj->base);

            /* The proper clock will be connected by i2c_init_clock(obj, I2C_DEFAULT_SPEED) */
            obj->divider = I2C_DIVIDER_LOW;
        } else {
#if DEVICE_SLEEP && DEVICE_LPTICKER
            /* Register callback once */
            obj->pm_callback_handler.callback = i2c_pm_callback;
            obj->pm_callback_handler.type = CY_SYSPM_DEEPSLEEP;
            obj->pm_callback_handler.skipMode = 0;
            obj->pm_callback_handler.callbackParams = &obj->pm_callback_params;
            obj->pm_callback_params.base = obj->base;
            obj->pm_callback_params.context = obj;
            if (!Cy_SysPm_RegisterCallback(&obj->pm_callback_handler)) {
                error("PM callback registration failed!");
            }
#endif /* DEVICE_SLEEP && DEVICE_LPTICKER */
        }

        /* Configure hardware resources */
        i2c_init_clock(obj, I2C_DEFAULT_SPEED);
        i2c_init_pins(obj);
        i2c_init_peripheral(obj);

    } else {
        error("I2C pinout mismatch. Requested pins SDA and SCL can't be used for the same I2C communication.");
    }
}
Beispiel #10
0
void spi_abort_asynch(spi_t *obj_in)
{
    spi_obj_t *obj = OBJ_P(obj_in);
    Cy_SCB_SPI_AbortTransfer(obj->base, &obj->context);
}
Beispiel #11
0
uint8_t spi_active(spi_t *obj_in)
{
    spi_obj_t *obj = OBJ_P(obj_in);
    return (obj->pending != PENDING_NONE);
}
Beispiel #12
0
void spi_master_transfer(spi_t *obj_in,
                         const void *tx,
                         size_t tx_length,
                         void *rx,
                         size_t rx_length,
                         uint8_t bit_width,
                         uint32_t handler,
                         uint32_t event,
                         DMAUsage hint)
{
    spi_obj_t *obj = OBJ_P(obj_in);

    (void)hint; // At the moment we do not support DAM transfers, so this parameter gets ignored.

    if (obj->pending != PENDING_NONE) {
        return;
    }

    // Validate buffer parameters.
    if (((obj->data_bits <= 8) && (bit_width != 8)) || ((obj->data_bits > 8) && (bit_width != 16))) {
        error("spi: buffer configurations does not match device configuration");
        return;
    }

    obj->events = event;
    obj->handler = handler;
    if (spi_irq_setup_channel(obj) < 0) {
        return;
    }

    if (tx_length > rx_length) {
        if (rx_length > 0) {
            // I) write + read, II) write only
            obj->pending = PENDING_TX_RX;
            obj->rx_buffer = NULL;
            obj->tx_buffer = (bit_width == 8)?
                             (void*)(((uint8_t*)tx) + rx_length) :
                             (void*)(((uint16_t*)tx) + rx_length);
            obj->tx_buffer_size = tx_length - rx_length;
            Cy_SCB_SPI_Transfer(obj->base, (void*)tx, rx, rx_length, &obj->context);
        } else {
            // I) write only.
            obj->pending = PENDING_TX;
            obj->rx_buffer = NULL;
            obj->tx_buffer = NULL;
            Cy_SCB_SPI_Transfer(obj->base, (void*)tx, NULL, tx_length, &obj->context);
        }
    } else if (rx_length > tx_length) {
        if (tx_length > 0) {
            // I) write + read, II) read only
            obj->pending = PENDING_TX_RX;
            obj->rx_buffer = (bit_width == 8)?
                             (void*)(((uint8_t*)rx) + tx_length) :
                             (void*)(((uint16_t*)rx) + tx_length);
            obj->rx_buffer_size = rx_length - tx_length;
            obj->tx_buffer = NULL;
            Cy_SCB_SPI_Transfer(obj->base, (void*)tx, rx, tx_length, &obj->context);
        } else {
            // I) read only.
            obj->pending = PENDING_RX;
            obj->rx_buffer = NULL;
            obj->tx_buffer = NULL;
            Cy_SCB_SPI_Transfer(obj->base, NULL, rx, rx_length, &obj->context);
        }
    } else {
        // Rx and Tx of the same size
        // I) write + read.
        obj->pending = PENDING_TX_RX;
        obj->rx_buffer = NULL;
        obj->tx_buffer = NULL;
        Cy_SCB_SPI_Transfer(obj->base, (void*)tx, rx, tx_length, &obj->context);
    }
}
Beispiel #13
0
uint8_t spi_get_module(spi_t *obj_in)
{
    return (uint8_t) OBJ_P(obj_in)->spi_id;
}
Beispiel #14
0
int  spi_busy(spi_t *obj)
{
    return !Cy_SCB_SPI_IsTxComplete(OBJ_P(obj)->base);
}