Once your hardware setup is correct you can try this code
Stream& out = Serial1;
SerialLogHandler logger(LOG_LEVEL_ERROR, {{ "app", LOG_LEVEL_INFO }});
const int MAX_COMMAND_LEN = 8;
enum CD160_CMD
{ CARD_LOAD_FRONT = 0
, CARD_EJECT_FRONT
, CARD_EJECT_BACK
, CARD_STACK_READ
, CARD_DISPENSE
, INFO_VERSION
, CARD_READ_POS1
, CARD_READ_POS2
, CARD_SWAP_POS
, INFO_STATE
, INFO_TEST
, CTRL_RESET
, CTRL_SHUTTER
, INFO_POS
, BARCODE_INIT
, BARCODE_READ
, DATA_PASSTHROUGH
, DATA_RAW
};
const uint8_t cmd[][MAX_COMMAND_LEN] =
// len prefix cmd checksum (precalculated but not used)
{ { 0x02, 0x96, 0x01, 0xf5 }
, { 0x03, 0x96, 0x02, 0x01, 0xf6 }
, { 0x03, 0x96, 0x02, 0x02, 0xf5 }
, { 0x02, 0x96, 0x03, 0xf7 }
, { 0x02, 0x96, 0x04, 0xf0 }
, { 0x02, 0x96, 0x06, 0xf2 }
, { 0x03, 0x96, 0x07, 0x01, 0xf3 }
, { 0x03, 0x96, 0x07, 0x02, 0xf0 }
, { 0x02, 0x96, 0x08, 0xfc }
, { 0x02, 0x96, 0x09, 0xfd }
, { 0x02, 0x96, 0x0A, 0xfe }
, { 0x02, 0x96, 0x0B, 0xff }
, { 0x02, 0x96, 0x0C, 0xf8 }
, { 0x02, 0x96, 0x0D, 0xf9 }
, { 0x02, 0x96, 0x10, 0xe4 }
, { 0x02, 0x96, 0x11, 0xe5 }
, { 0x02, 0x96, 0x20 } // checksum cannot be precalculated w/o additional data
, { 0x00 } // checksum cannot be precalculated w/o additional data
};
uint8_t sendTLP224(const uint8_t* data, size_t len = 0);
uint8_t sendTLP224(CD160_CMD idxCommand, const uint8_t* data = NULL, size_t len = 0);
void setup() {
System.on(button_click, btnHandler);
Serial1.blockOnOverrun(false);
Serial1.begin(9600);
Log.info("Command list");
for (int i=0; i < DATA_PASSTHROUGH; i++)
Log.info("checksum for %2d: 0x%02X", i, sendTLP224((CD160_CMD)i));
}
void loop() {
}
void btnHandler(system_event_t event, int param) {
Serial.printlnf("INFO_STATE request sent (checkSum: %02x)", sendTLP224(INFO_STATE));
}
void serialEvent1() {
return;
char c;
while(Serial1.available()) {
c = Serial1.read();
Serial.printf("%c (0x%02X)%s", c, c, (c == '\x03' ? "\r\n" : " ") );
}
}
uint8_t sendTLP224(CD160_CMD idxCommand, const uint8_t* data, size_t len) {
uint8_t lenRaw = cmd[idxCommand][0] + 1; // first byte of cmd indicates command length (w/o length byte itself)
uint8_t command[lenRaw + len]; // reserve data for combination of command and additional data
memcpy(command, cmd[idxCommand], lenRaw); // copy over the raw command
memcpy(command+lenRaw, data, len); // copy additional data
command[0] = sizeof(command) - 1; // new/combined length (length byte doesn't count itself, hence -1)
return sendTLP224(command, sizeof(command)); // call actual protocol algo
}
uint8_t sendTLP224(const uint8_t* data, size_t len) {
uint8_t checkSum = 0x60; // ACK byte per protocol definition
char tx[4];
if (!data) return 0xFF; // when no data is provided, nothing to do
if (!len) len = data[0] + 1; // when no length is provided, the first byte of the provided data must be the length indicator
out.print("60"); // always acknowledge, even an initial transmission
for (int i = 0; i < len; i++) {
checkSum ^= data[i]; // XOR checkSum with current byte
snprintf(tx, sizeof(tx), "%02X", data[i]); // translate binary byte to ASCII string representation
out.print(tx); // emit packet
}
snprintf(tx, sizeof(tx), "%02X\x03", checkSum); // emit checksum and ETX as per protocol definition
out.print(tx); //
return checkSum;
}
(press the SETUP/MODE button to emit a state request and check the response via particle serial monitor --follow
)