nfc support working on tag, no esp32 yet

This commit is contained in:
Jelmer
2023-03-07 21:52:00 +01:00
parent 99c51d3654
commit 3abf3de984
12 changed files with 259 additions and 23 deletions

View File

@@ -5,7 +5,7 @@ BUILD ?= zbs29v033
SOURCES += main.c eeprom.c drawing.c
SOURCES += comms.c
SOURCES += syncedproto.c userinterface.c
SOURCES += powermgt.c barcode.c
SOURCES += powermgt.c barcode.c i2cdevices.c
all: #make sure it is the first target

Binary file not shown.

Binary file not shown.

Binary file not shown.

109
tag_fw/i2cdevices.c Normal file
View File

@@ -0,0 +1,109 @@
// data / _command: 2.2
// _select 1.7
// busy 2.1
// reset 2.0
// spi.clk 0.0
// spi.mosi 0.1
#include "i2cdevices.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "cpu.h"
#include "i2c.h"
#include "printf.h"
#include "timer.h"
extern void dump(uint8_t* __xdata a, uint16_t __xdata l); // remove me when done
extern uint8_t __xdata blockXferBuffer[];
__xdata uint8_t i2cbuffer[18];
void loadRawNTag(uint16_t blocksize) {
struct I2cTransaction __xdata i2ctrans;
if (blocksize > 864) blocksize = 864;
uint8_t trcount = (uint8_t)(blocksize / 16);
if (blocksize % 16) trcount++;
for (uint8_t c = 0; c < trcount; c++) {
i2ctrans.numBytes = 17;
i2ctrans.deviceAddr = (uint8_t)0x55 << 1;
i2ctrans.bytes = i2cbuffer;
i2cbuffer[0] = c + 1;
memcpy(i2cbuffer + 1, blockXferBuffer + (c * 16), 16);
uint8_t res = i2cTransact(&i2ctrans, 1);
timerDelay(133300);
}
}
void loadURLtoNTag() {
// https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef << very helpful
uint8_t __xdata i2cbuffer[18];
__xdata uint8_t* tempbuffer = blockXferBuffer + 2048;
strncpy(tempbuffer + 7, blockXferBuffer, 245);
uint8_t __xdata len = strlen(tempbuffer + 7);
struct I2cTransaction __xdata i2ctrans;
// TLV
tempbuffer[0] = 0x03; // NDEF message (TLV type)
tempbuffer[1] = 4 + len + 1;
// ndef record
tempbuffer[2] = 0xD1;
tempbuffer[3] = 0x01; // well known record type
tempbuffer[4] = len + 1; // payload length
tempbuffer[5] = 0x55; // payload type (URI record)
tempbuffer[6] = 0x00; // URI identifier code (no prepending)
len = 7 + len;
tempbuffer[len] = 0xFE;
uint8_t trcount = len / 16;
if (len % 16) trcount++;
for (uint8_t c = 0; c < trcount; c++) {
i2ctrans.numBytes = 17;
i2ctrans.deviceAddr = (uint8_t)0x55 << 1;
i2ctrans.bytes = i2cbuffer;
i2cbuffer[0] = c + 1;
memcpy(i2cbuffer + 1, tempbuffer + (c * 16), 16);
uint8_t res = i2cTransact(&i2ctrans, 1);
timerDelay(133300);
}
}
void i2cBusScan() {
struct I2cTransaction __xdata iictest;
iictest.numBytes = 0;
iictest.bytes = NULL;
pr("Starting I2C scan...\n");
for (uint8_t address = 0x00; address <= 0x7F; address++) {
iictest.deviceAddr = address << 1;
uint8_t res = i2cTransact(&iictest, 1);
if (res == 0) {
pr(" - Found i2c device at %02X\n", address);
}
timerDelay(13330);
}
pr("I2C scan complete\n");
}
bool i2cCheckDevice(uint8_t address) {
struct I2cTransaction __xdata iictest;
iictest.numBytes = 0;
iictest.deviceAddr = address << 1;
uint8_t res = i2cTransact(&iictest, 1);
if (res == 0) {
pr("Found i2c device at 0x%02X\n", address);
return true;
}
return false;
}

9
tag_fw/i2cdevices.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef _I2CDEV_H_
#define _I2CDEV_H_
#include <stdint.h>
void loadURLtoNTag();
void loadRawNTag(uint16_t blocksize);
bool i2cCheckDevice(uint8_t address);
#endif

View File

@@ -8,11 +8,13 @@
#include "asmUtil.h"
#include "comms.h" // for mLastLqi and mLastRSSI
#include "eeprom.h"
#include "screen.h"
#include "i2c.h"
#include "i2cdevices.h"
#include "powermgt.h"
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "screen.h"
#include "settings.h"
#include "syncedproto.h"
#include "timer.h"
@@ -21,8 +23,10 @@
// #define DEBUG_MODE
uint8_t __xdata capabilities = 0;
void displayLoop() {
powerUp(INIT_BASE | INIT_UART | INIT_GPIO);
powerUp(INIT_BASE | INIT_UART);
pr("Splash screen\n");
powerUp(INIT_EPD);
@@ -178,6 +182,15 @@ void main() {
pr("BOOTED> %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
#ifdef HAS_BUTTON
capabilities |= CAPABILITY_HAS_WAKE_BUTTON;
#endif
powerUp(INIT_I2C);
if (i2cCheckDevice(0x55)){
capabilities |= CAPABILITY_HAS_NFC;
}
powerDown(INIT_I2C);
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);

View File

@@ -12,11 +12,12 @@
#include "cpu.h"
#include "drawing.h"
#include "eeprom.h"
#include "screen.h"
#include "i2c.h"
#include "i2cdevices.h"
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "screen.h"
#include "settings.h"
#include "sleep.h"
#include "syncedproto.h"
@@ -41,7 +42,7 @@ uint16_t __xdata voltageCheckCounter = 0;
bool __xdata spiActive = false;
bool __xdata uartActive = false;
bool __xdata eepromActive = false;
bool __xdata i2cActive = false;
extern int8_t adcSampleTemperature(void); // in degrees C
void setupPortsInitial() {
@@ -118,7 +119,27 @@ static void configEEPROM(const bool setup) {
} else {
P1DIR |= (1 << 1);
}
setup == eepromActive;
setup == eepromActive; // wtf, this does nothing.
}
static void configI2C(const bool setup) {
if (setup == i2cActive) return;
if (setup) {
P1DIR &= ~(1 << 6);
P1_6 = 1;
P1FUNC |= (1 << 4) | (1 << 5);
P1PULL |= (1 << 4) | (1 << 5);
i2cInit();
i2cCheckDevice(0x50); // first transaction after init fails, this makes sure everything is ready for the first transaction
} else {
P1DIR |= (1 << 6);
P1_6 = 0;
P1FUNC &= ~((1 << 4) | (1 << 5));
P1PULL &= ~((1 << 4) | (1 << 5));
CLKEN &= ~0x10;
IEN1 &= ~4;
}
i2cActive = setup;
}
void powerUp(const uint8_t parts) {
@@ -171,13 +192,16 @@ void powerUp(const uint8_t parts) {
radioSetChannel(RADIO_FIRST_CHANNEL);
}
}
if (parts & INIT_I2C) {
configI2C(true);
}
}
void powerDown(const uint8_t parts) {
if (parts & INIT_UART) {
configUART(false);
}
if (parts & INIT_RADIO) { // warning; this also touches some stuff about the EEPROM, apparently. Re-init EEPROM afterwards
if (parts & INIT_RADIO) { // warning; this also touches some stuff about the EEPROM, apparently. Re-init EEPROM afterwards
radioRxEnable(false, true);
RADIO_IRQ4_pending = 0;
UNK_C1 &= ~0x81;
@@ -201,6 +225,9 @@ void powerDown(const uint8_t parts) {
if (!eepromActive && !epdGPIOActive) {
configSPI(false);
}
if (parts & INIT_I2C) {
configI2C(false);
}
}
void doSleep(const uint32_t __xdata t) {

View File

@@ -11,7 +11,7 @@
#define INIT_EPD_VOLTREADING 0x80
#define INIT_RADIO 0x40
#define INIT_GPIO 0x20
#define INIT_I2C 0x20
#define INIT_UART 0x10
#define INIT_EPD 0x08
#define INIT_EEPROM 0x04

View File

@@ -111,28 +111,31 @@ struct AvailDataReq {
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities; // undefined, as of now
uint8_t capabilities; // undefined, as of now
} __packed;
#define CAPABILITY_HAS_WAKE_BUTTON 0x20
#define CAPABILITY_HAS_NFC 0x40
#define DATATYPE_NOUPDATE 0
#define DATATYPE_IMG_BMP 2
#define DATATYPE_FW_UPDATE 3
#define DATATYPE_IMG_DIFF 0x10 // always 1BPP
#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2"
#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2"
#define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD
#define DATATYPE_IMG_DIFF 0x10 // always 1BPP
#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2"
#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2"
#define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD
#define DATATYPE_NFC_RAW_CONTENT 0xA0 // raw memory content for the NT3H1101
#define DATATYPE_NFC_URL_DIRECT 0xA1 // URL format for NT3H1101
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
uint8_t dataType;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
uint8_t dataType;
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
} __packed;
struct blockPart {
uint8_t checksum;
uint8_t blockId;

View File

@@ -13,17 +13,17 @@
#include "cpu.h"
#include "drawing.h"
#include "eeprom.h"
#include "i2c.h"
#include "i2cdevices.h"
#include "powermgt.h"
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "screen.h"
#include "settings.h"
#include "sleep.h"
#include "timer.h"
#include "userinterface.h"
#include "wdt.h"
#include "screen.h"
// download-stuff
uint8_t __xdata blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0};
@@ -50,6 +50,9 @@ uint8_t __xdata currentChannel = 0;
static uint8_t __xdata inBuffer[128] = {0};
static uint8_t __xdata outBuffer[128] = {0};
// get capabilities from main.c
extern uint8_t __xdata capabilities;
// tools
static uint8_t __xdata getPacketType(const void *__xdata buffer) {
const struct MacFcs *__xdata fcs = buffer;
@@ -192,6 +195,7 @@ static void sendAvailDataReq() {
availreq->lastPacketLQI = mLastLqi;
availreq->temperature = temperature;
availreq->batteryMv = batteryVoltage;
availreq->capabilities = capabilities;
addCRC(availreq, sizeof(struct AvailDataReq));
commsTxNoCpy(outBuffer);
}
@@ -479,7 +483,7 @@ static bool getDataBlock(const uint16_t blockSize) {
partsThisBlock = BLOCK_MAX_PARTS;
memset(curBlock.requestedParts, 0xFF, BLOCK_REQ_PARTS_BYTES);
} else {
partsThisBlock = (sizeof(struct blockData)+blockSize) / BLOCK_PART_DATA_SIZE;
partsThisBlock = (sizeof(struct blockData) + blockSize) / BLOCK_PART_DATA_SIZE;
if (blockSize % BLOCK_PART_DATA_SIZE) partsThisBlock++;
memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES);
for (uint8_t c = 0; c < partsThisBlock; c++) {
@@ -698,7 +702,7 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
}
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
if (avail->dataSize > 4096) avail->dataSize = 4096;
if (getDataBlock(avail->dataSize)) {
powerUp(INIT_RADIO);
sendXferComplete();
@@ -792,6 +796,50 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
return false;
}
break;
case DATATYPE_NFC_URL_DIRECT:
case DATATYPE_NFC_RAW_CONTENT:
// Handle data for the NFC IC (if we have it)
// check if we actually have the capability to do NFC
if (!(capabilities & CAPABILITY_HAS_NFC)) {
// looks like we don't. mark as complete and then bail!
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
}
pr("NFC URL received\n");
if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) {
// we've already downloaded this NFC data, disregard and send XFC
pr("this was the same as the last transfer, disregard\n");
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
}
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
uint16_t __xdata nfcsize = avail->dataSize;
if (getDataBlock(avail->dataSize)) {
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
curDataInfo.dataSize = 0; // mark as transfer not pending
powerUp(INIT_I2C);
if (avail->dataType == DATATYPE_NFC_URL_DIRECT) {
// only one URL (handle NDEF records on the tag)
loadURLtoNTag();
} else {
// raw NFC data upload to the NFC IC
loadRawNTag(nfcsize);
}
powerDown(INIT_I2C);
return true;
}
return false;
break;
}
return true;
}

View File

@@ -20,6 +20,7 @@
#include "spi.h"
#include "syncedproto.h" // for APmac / Channel
#include "timer.h"
#include "proto.h"
// extern uint8_t __xdata mSelfMac[8];
// extern uint8_t __xdata currentChannel;
@@ -29,9 +30,21 @@
const uint8_t __code fwVersion = FW_VERSION;
const char __code fwVersionSuffix[] = FW_VERSION_SUFFIX;
extern uint8_t __xdata capabilities;
bool __xdata lowBatteryShown = false;
bool __xdata noAPShown = false;
void addCapabilities() {
epdpr("Options: ");
if (capabilities & CAPABILITY_HAS_NFC) {
epdpr("-NFC ");
}
if (capabilities & CAPABILITY_HAS_WAKE_BUTTON) {
epdpr("-WAKE BUTTON" );
}
}
void addOverlay() {
if (currentChannel == 0) {
#if (SCREEN_WIDTH == 152)
@@ -83,6 +96,10 @@ void showSplashScreen() {
epdpr("%02X%02X", mSelfMac[1], mSelfMac[0]);
epdPrintEnd();
epdPrintBegin(2, 104, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
addCapabilities();
epdPrintEnd();
epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("zbs154v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
epdPrintEnd();
@@ -95,6 +112,11 @@ void showSplashScreen() {
epdpr("Starting");
epdPrintEnd();
epdPrintBegin(64, 295, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
addCapabilities();
epdPrintEnd();
epdPrintBegin(80, 295, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("zbs29v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
epdPrintEnd();
@@ -106,6 +128,7 @@ void showSplashScreen() {
epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]);
epdPrintEnd();
uint8_t __xdata buffer[17];
spr(buffer, "%02X%02X", mSelfMac[7], mSelfMac[6]);
spr(buffer + 4, "%02X%02X", mSelfMac[5], mSelfMac[4]);
@@ -126,6 +149,10 @@ void showSplashScreen() {
epdpr("Starting");
epdPrintEnd();
epdPrintBegin(2, 252, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
addCapabilities();
epdPrintEnd();
epdPrintBegin(3, 268, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("zbs42v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
epdPrintEnd();
@@ -421,7 +448,7 @@ void showNoEEPROM() {
epdPrintEnd();
#endif
#if (SCREEN_WIDTH == 400) // 4.2"
epdPrintBegin(50 , 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdPrintBegin(50, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("EEPROM FAILED :(");
epdPrintEnd();
loadRawBitmap(failed, 176, 126, EPD_COLOR_RED);