/** * Sends the three bytes comprising a read command to the 14CUX. * @param addr 16-bit address at which to read * @param len Number of bytes to read * @param lastByteOnly Send only the last byte of the read command; this will * work only if the coarse address was previously set. * @return True when the read command is successfully sent; false otherwise */ bool c14cux_sendReadCmd(c14cux_info* info, uint16_t addr, uint16_t len, bool lastByteOnly) { bool success = 0; uint8_t cmdByte = 0; // do the command-agnostic coarse address setup // (req'd for both reads and writes) if (lastByteOnly || c14cux_setReadCoarseAddr(info, addr, len)) { // if we actually did send the command bytes to set a new coarse // address, then remember what it was if (!lastByteOnly) { info->lastReadCoarseAddress = addr; } // build and send the byte for the Read command cmdByte = ((addr & 0x003F) | 0xC0); dprintf_info("14CUX(info): Sending Read command byte: 0x%02X... (no echo)\n", cmdByte); if (c14cux_writeSerialBytes(info, &cmdByte, 1) == 1) { // The 14CUX doesn't echo the Read command byte; // it simply starts sending the requested data. // Because of this, we can consider the command // successfully sent without checking for an echo // of the last byte. success = true; } else { dprintf_err("14CUX(error): Faled to write byte!\n"); } } return success; }
/** * Sends command bytes to the 14CUX to set the coarse address for either a * read or write operation. If the command is ultimately a write operation, * the 14CUX will ignore the length. * @param addr Memory address at which the read or write will occur. * @param len Number of bytes to retrieve when the read operation is executed. * @return True when the command bytes were sent and echoed properly; false otherwise */ bool c14cux_setCoarseAddr(c14cux_info* info, uint16_t addr, uint16_t len) { uint8_t firstByte = 0x00; uint8_t secondByte = 0x00; uint8_t readByte = 0x00; bool retVal = false; dprintf_info("14CUX(info): Sending command to set coarse address...\n"); if (len == 0) { // if zero was passed for the length, we assume that this address // selection is being done for a write operation (which does not // require a quantity) firstByte = 0; } else if (len <= C14CUX_ReadCount0) { // if we're reading between 1 and 16 bytes, set the byte value // to (len - 1), which is interpreted by the 14CUX as (len) firstByte = len - 1; } else { // otherwise, we check to ensure that len is one of the allowed // preset values; if it isn't, return failure if (len == C14CUX_ReadCount1) { firstByte = C14CUX_ReadCount1Value; } else if (len == C14CUX_ReadCount2) { firstByte = C14CUX_ReadCount2Value; } else if (len == C14CUX_ReadCount3) { firstByte = C14CUX_ReadCount3Value; } else if (len == C14CUX_ReadCount4) { firstByte = C14CUX_ReadCount4Value; } else { dprintf_err("14CUX(error): Invalid length.\n"); return 0; } } // bit 7 is fixed low; bits 6:2 are the read quantity, // and bits 1:0 are the top two bits (15:14) of the address firstByte <<= 2; firstByte |= (addr >> 14); dprintf_info("14CUX(info): Sending byte: 0x%02X...\n", firstByte); if ((c14cux_writeSerialBytes(info, &firstByte, 1) == 1) && (c14cux_readSerialBytes(info, &readByte, 1) == 1) && (readByte == firstByte)) { // bits 13:6 of the address secondByte = ((addr >> 6) & 0x00ff); dprintf_info("14CUX(info): Sending byte: 0x%02X...\n", secondByte); if ((c14cux_writeSerialBytes(info, &secondByte, 1) == 1) && (c14cux_readSerialBytes(info, &readByte, 1) == 1) && (readByte == secondByte)) { retVal = true; } }