Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
/**
 * Reads the specified number of bytes from memory at the specified address.
 * @param info State information for the active connection.
 * @param addr Address at which memory should be read.
 * @param len Number of bytes to read.
 * @param buffer Pointer to a buffer of at least len bytes
 * @return 1 when the operation was successful; 0 otherwise
 */
bool c14cux_readMem(c14cux_info* info, uint16_t addr, uint16_t len, uint8_t* buffer)
{
#if defined(WIN32)
    if (WaitForSingleObject(info->mutex, INFINITE) != WAIT_OBJECT_0)
    {
        return 0;
    }
#else
    pthread_mutex_lock(&info->mutex);
#endif

    uint16_t totalBytesRead = 0;
    uint16_t singleReqQuantity = 0;
    uint16_t singleReqBytesRead = 0;
    bool readSuccess = false;
    int16_t readCallBytesRead = 1;
    bool sendLastByteOnly = false;

    info->cancelRead = 0;

    if (c14cux_isConnected(info))
    {
        // loop until we've read all the bytes, or we experienced a read error
        while ((totalBytesRead < len) && (readCallBytesRead > 0) && (info->cancelRead == 0))
        {
            // read the maximum number of bytes as is reasonable
            singleReqQuantity = c14cux_getByteCountForNextRead(len, totalBytesRead);

            // if the next address to read is within the 64-byte window
            // created by the last coarse address that was set, then we
            // can just send the final byte of the read command
            sendLastByteOnly =
                ((singleReqQuantity == info->lastReadQuantity) &&
                 ((addr + totalBytesRead) < (info->lastReadCoarseAddress + 64)) &&
                 (info->lastReadCoarseAddress <= (addr + totalBytesRead)));

            dprintf_info("14CUX(info): Sending cmd to read %d bytes at 0x%04X...\n",
                singleReqQuantity, addr + totalBytesRead);

            // if sending the read command is successful...
            if (c14cux_sendReadCmd(info, addr + totalBytesRead, singleReqQuantity, sendLastByteOnly))
            {
                dprintf_info("14CUX(info): Successfully sent read command.\n");

                // reset the number of bytes read during this single read operation
                singleReqBytesRead = 0;

                // loop until we've read all the bytes for this single read operation,
                // or until we time out
                do
                {
                    readCallBytesRead =
                        c14cux_readSerialBytes(info, buffer + totalBytesRead + singleReqBytesRead,
                                               singleReqQuantity - singleReqBytesRead);

                    singleReqBytesRead += readCallBytesRead;
                }
                while ((readCallBytesRead > 0) && (singleReqBytesRead < singleReqQuantity));

                // if all the reads were successful, add the total bytes
                // read from this request to the overall total
                if (readCallBytesRead > 0)
                {
                    dprintf_info("14CUX(info): Successfully read %d bytes.\n", singleReqBytesRead);
                    totalBytesRead += singleReqBytesRead;

                    // remember the number of bytes read on this pass, in case we
                    // want to issue an abbreviated command next time (which will
                    // send the same number of bytes)
                    info->lastReadQuantity = singleReqQuantity;
                }
            }
            else
            {
                // if we were unable to even send the read command,
                // stop with failure
                dprintf_err("14CUX(error): Failed to send read command\n");
                readCallBytesRead = -1;
            }
        }
    }

    // if we read as many bytes as were requested, indicate success
    if (totalBytesRead == len)
    {
        dprintf_info("14CUX(info): Successfully read all requested bytes.\n");
        readSuccess = true;
    }
    else
    {
        info->lastReadCoarseAddress = 0;
        info->lastReadQuantity = 0;
    }

#if defined(WIN32)
    ReleaseMutex(info->mutex);
#else
    pthread_mutex_unlock(&info->mutex);
#endif

    return readSuccess;
}
Exemplo n.º 3
0
/**
 * 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;
        }
    }