Merge pull request #306 from merlokk/lf_read_adc

Adds generic ADC read functionality
This commit is contained in:
GameTec-live
2026-02-07 20:42:25 +01:00
committed by GitHub
9 changed files with 137 additions and 0 deletions
+1
View File
@@ -345,6 +345,7 @@ ifeq (${CURRENT_DEVICE_TYPE}, ${CHAMELEON_ULTRA})
$(PROJ_DIR)/rfid/reader/lf/lf_t55xx_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_hidprox_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_viking_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_reader_generic.c \
INC_FOLDERS +=\
${PROJ_DIR}/rfid/reader/ \
+27
View File
@@ -737,6 +737,32 @@ static data_frame_tx_t *cmd_processor_viking_write_to_t55xx(uint16_t cmd, uint16
status = write_viking_to_t55xx(payload->id, payload->new_key, payload->old_keys, (length - offsetof(payload_t, old_keys)) / sizeof(payload->old_keys));
return data_frame_make(cmd, status, 0, NULL);
}
#define GENERIC_READ_LEN 800
#define GENERIC_READ_TIMEOUT_MS 500
static data_frame_tx_t *cmd_processor_generic_read(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t *outdata = malloc(GENERIC_READ_LEN);
if (outdata == NULL) {
return data_frame_make(cmd, STATUS_MEM_ERR, 0, NULL);
}
size_t outlen = 0;
if (!raw_read_to_buffer(outdata, GENERIC_READ_LEN, GENERIC_READ_TIMEOUT_MS, &outlen)) {
free(outdata);
return data_frame_make(cmd, STATUS_CMD_ERR, 0, NULL);
};
data_frame_tx_t *frame = data_frame_make(cmd, STATUS_LF_TAG_OK, outlen, outdata);
free(outdata);
if (frame == NULL) {
return data_frame_make(cmd, STATUS_CREATE_RESPONSE_ERR, 0, NULL);
}
return frame;
}
#endif
@@ -1671,6 +1697,7 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_HIDPROX_WRITE_TO_T55XX, before_reader_run, cmd_processor_hidprox_write_to_t55xx, NULL },
{ DATA_CMD_VIKING_SCAN, before_reader_run, cmd_processor_viking_scan, NULL },
{ DATA_CMD_VIKING_WRITE_TO_T55XX, before_reader_run, cmd_processor_viking_write_to_t55xx, NULL },
{ DATA_CMD_ADC_GENERIC_READ, before_reader_run, cmd_processor_generic_read, NULL },
{ DATA_CMD_HF14A_SET_FIELD_ON, before_reader_run, cmd_processor_hf14a_set_field_on, NULL },
{ DATA_CMD_HF14A_SET_FIELD_OFF, before_reader_run, cmd_processor_hf14a_set_field_off, NULL },
+4
View File
@@ -31,5 +31,9 @@
#define STATUS_FLASH_WRITE_FAIL (0x70) // Flash writing failed
#define STATUS_FLASH_READ_FAIL (0x71) // Flash read failed
#define STATUS_INVALID_SLOT_TYPE (0x72) // Invalid slot type
#define STATUS_MEM_ERR (0x73) // Can't allocate memory or work with memory error
#define STATUS_CREATE_RESPONSE_ERR (0x74) // Can't create response for command
#define STATUS_CMD_ERR (0x75) // Execution of command failed
#endif
+3
View File
@@ -95,6 +95,9 @@
#define DATA_CMD_HIDPROX_WRITE_TO_T55XX (3003)
#define DATA_CMD_VIKING_SCAN (3004)
#define DATA_CMD_VIKING_WRITE_TO_T55XX (3005)
#define DATA_CMD_ADC_GENERIC_READ (3006)
#define DATA_CMD_GENERIC_READ (3007)
#define DATA_CMD_CORR_GENERIC_READ (3008)
//
// ******************************************************************
@@ -22,6 +22,8 @@ bool em410x_read(uint8_t *data, uint32_t timeout_ms);
bool hidprox_read(uint8_t *data, uint8_t format_hint, uint32_t timeout_ms);
bool viking_read(uint8_t *data, uint32_t timeout_ms);
bool raw_read_to_buffer(uint8_t *data, size_t maxlen, uint32_t timeout_ms, size_t *outlen);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,60 @@
#include "lf_reader_data.h"
#include "bsp_delay.h"
#include "bsp_time.h"
#include "circular_buffer.h"
#include "lf_125khz_radio.h"
#include "lf_reader_data.h"
#include "protocols/protocols.h"
#define NRF_LOG_MODULE_NAME lfgeneric
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
#define CIRCULAR_BUFFER_SIZE (128)
static circular_buffer cb;
// saadc irq is used to sample ANT GPIO.
static void saadc_cb(nrf_saadc_value_t *vals, size_t size) {
for (int i = 0; i < size; i++) {
nrf_saadc_value_t val = vals[i];
if (!cb_push_back(&cb, &val)) {
return;
}
}
}
static void init_saadc_hw(void) {
lf_125khz_radio_saadc_enable(saadc_cb);
}
static void uninit_saadc_hw(void) {
lf_125khz_radio_saadc_disable();
}
bool raw_read_to_buffer(uint8_t *data, size_t maxlen, uint32_t timeout_ms, size_t *outlen) {
*outlen = 0;
cb_init(&cb, CIRCULAR_BUFFER_SIZE, sizeof(uint16_t));
init_saadc_hw();
start_lf_125khz_radio();
autotimer *p_at = bsp_obtain_timer(0);
while (NO_TIMEOUT_1MS(p_at, timeout_ms) && *outlen < maxlen) {
uint16_t val = 0;
while (cb_pop_front(&cb, &val) && *outlen < maxlen) {
val = val >> 5; // 14 bit ADC to 8 bit value and /2 range
data[*outlen] = val > 0xff ? 0xff : val;
++(*outlen);
}
}
bsp_return_timer(p_at);
stop_lf_125khz_radio();
uninit_saadc_hw();
cb_free(&cb);
return true;
}
+27
View File
@@ -553,6 +553,7 @@ lf_em_410x = lf_em.subgroup('410x', 'EM410x commands')
lf_hid = lf.subgroup('hid', 'HID commands')
lf_hid_prox = lf_hid.subgroup('prox', 'HID Prox commands')
lf_viking = lf.subgroup('viking', 'Viking commands')
lf_generic = lf.subgroup('generic', 'Generic commands')
@root.command('clear')
class RootClear(BaseCLIUnit):
@@ -3827,6 +3828,32 @@ class LFVikingWriteT55xx(LFVikingIdArgsUnit, ReaderRequiredUnit):
self.cmd.viking_write_to_t55xx(id_bytes)
print(f" - Viking ID(8H): {id_hex} write done.")
@lf_generic.command('adcread')
class LFADCGenericRead(ReaderRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit:
parser = ArgumentParserNoExit()
parser.description = 'Read ADC and return the array'
return parser
def on_exec(self, args: argparse.Namespace):
resp = self.cmd.adc_generic_read()
if resp is not None:
print(f"generic read data[{len(resp)}]:")
width = 50
for i in range(0, len(resp), width):
chunk = resp[i : i + width]
hexpart = " ".join(f"{b:02x}" for b in chunk)
binpart = "".join('1' if b >= 0xbf else '0' for b in chunk)
print(f"{i:04x} {hexpart:<{width * 3}} {binpart}")
avg = 0
for val in resp:
avg += val
print(f'avg: {hex(round(avg / len(resp)))}')
else:
print(f"generic read error")
@hw_slot.command('list')
class HWSlotList(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit:
+12
View File
@@ -534,6 +534,18 @@ class ChameleonCMD:
data = struct.pack(f'!4s4s{4*len(old_keys)}s', id_bytes, new_key, b''.join(old_keys))
return self.device.send_cmd_sync(Command.VIKING_WRITE_TO_T55XX, data)
@expect_response(Status.LF_TAG_OK)
def adc_generic_read(self):
"""
Read the ADC when the field is on.
:return:
"""
resp = self.device.send_cmd_sync(Command.ADC_GENERIC_READ, None)
if resp.status == Status.LF_TAG_OK:
resp.parsed = resp.data
return resp
@expect_response(Status.SUCCESS)
def get_slot_info(self):
"""
+1
View File
@@ -83,6 +83,7 @@ class Command(enum.IntEnum):
HIDPROX_WRITE_TO_T55XX = 3003
VIKING_SCAN = 3004
VIKING_WRITE_TO_T55XX = 3005
ADC_GENERIC_READ = 3006
MF1_WRITE_EMU_BLOCK_DATA = 4000
HF14A_SET_ANTI_COLL_DATA = 4001