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); }
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); } }
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; } }
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); } }
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; }
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); } }
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; }
uint8_t i2c_active(i2c_t *obj_in) { i2c_obj_t *obj = OBJ_P(obj_in); return (obj->pending != PENDING_NONE); }
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."); } }
void spi_abort_asynch(spi_t *obj_in) { spi_obj_t *obj = OBJ_P(obj_in); Cy_SCB_SPI_AbortTransfer(obj->base, &obj->context); }
uint8_t spi_active(spi_t *obj_in) { spi_obj_t *obj = OBJ_P(obj_in); return (obj->pending != PENDING_NONE); }
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); } }
uint8_t spi_get_module(spi_t *obj_in) { return (uint8_t) OBJ_P(obj_in)->spi_id; }
int spi_busy(spi_t *obj) { return !Cy_SCB_SPI_IsTxComplete(OBJ_P(obj)->base); }