Refactor, add initial PN532 support
This commit is contained in:
parent
42245e5f6c
commit
8dab83dad6
|
@ -1,34 +0,0 @@
|
|||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <MFRC522.h>
|
||||
#include <rdm6300.h>
|
||||
|
||||
class CardReader {
|
||||
public:
|
||||
virtual bool canHaveUnstableIdentifier() = 0;
|
||||
virtual bool isNewCardPresent() = 0;
|
||||
virtual String getCardUid() = 0;
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
class MFRC522CardReader : public CardReader {
|
||||
private:
|
||||
MFRC522* iReader;
|
||||
public:
|
||||
explicit MFRC522CardReader(MFRC522* reader);
|
||||
bool canHaveUnstableIdentifier() override;
|
||||
bool isNewCardPresent() override;
|
||||
String getCardUid() override;
|
||||
void reset() override;
|
||||
};
|
||||
|
||||
class RDM6300CardReader : public CardReader {
|
||||
private:
|
||||
Rdm6300* iReader;
|
||||
public:
|
||||
explicit RDM6300CardReader(Rdm6300* reader);
|
||||
bool canHaveUnstableIdentifier() override;
|
||||
bool isNewCardPresent() override;
|
||||
String getCardUid() override;
|
||||
void reset() override;
|
||||
};
|
|
@ -4,8 +4,20 @@
|
|||
#include "logos.h"
|
||||
#include "utils.h"
|
||||
|
||||
void drawLogo(U8G2 u8g2, e_logo logo);
|
||||
void drawStatusText(U8G2 u8g2, const String& status, const String& statusRightAligned = "");
|
||||
|
||||
void updateOLED(U8G2 u8g2, e_state state, const String& statusText, const String& statusTextRightAligned = "");
|
||||
void updateOLED(const U8G2& u8g2, e_state state);
|
||||
class OLED {
|
||||
private:
|
||||
U8G2 u8g2;
|
||||
String revision;
|
||||
void drawCurvedLineV(int xStart, int yStart, int vert, int horiz);
|
||||
void drawCurvedLine(int xStart, int yStart, int horiz, int vert);
|
||||
void drawLogoAfraPay();
|
||||
void drawLogoBitmap(int width, int height, unsigned char bits[], int yOffset = 0);
|
||||
void drawFullScreenText(const String& textTop, const String& textBottom);
|
||||
public:
|
||||
explicit OLED(U8G2 u8g2);
|
||||
void begin();
|
||||
void drawLogo(e_logo logo);
|
||||
void drawStatusText(const String& status, const String& statusRightAligned = "");
|
||||
void updateOLED(e_state state, const String& statusText, const String& statusTextRightAligned = "");
|
||||
void updateOLED(e_state state);
|
||||
};
|
||||
|
|
58
AfRApay.MateCard/include/readers.h
Normal file
58
AfRApay.MateCard/include/readers.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <MFRC522.h>
|
||||
#include <rdm6300.h>
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
virtual bool canHaveUnstableIdentifier() = 0;
|
||||
virtual bool isNewCardPresent() = 0;
|
||||
virtual String getCardUid() = 0;
|
||||
virtual void begin() = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void end() = 0;
|
||||
};
|
||||
|
||||
class MFRC522Reader : public Reader {
|
||||
private:
|
||||
MFRC522* mfrc522;
|
||||
public:
|
||||
explicit MFRC522Reader(byte chipSelectPin, byte resetPowerDownPin);
|
||||
bool canHaveUnstableIdentifier() override;
|
||||
bool isNewCardPresent() override;
|
||||
String getCardUid() override;
|
||||
void reset() override;
|
||||
void init() override;
|
||||
};
|
||||
|
||||
class RDM6300Reader : public Reader {
|
||||
private:
|
||||
Rdm6300* rdm6300;
|
||||
int pin;
|
||||
public:
|
||||
explicit RDM6300Reader(int pin);
|
||||
bool canHaveUnstableIdentifier() override;
|
||||
bool isNewCardPresent() override;
|
||||
String getCardUid() override;
|
||||
void reset() override;
|
||||
void init() override;
|
||||
};
|
||||
|
||||
class PN532Reader : public Reader {
|
||||
private:
|
||||
Adafruit_PN532* pn532;
|
||||
uint8_t uid[7];
|
||||
uint8_t uidLength;
|
||||
public:
|
||||
static volatile int irq;
|
||||
explicit PN532Reader(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss);
|
||||
bool canHaveUnstableIdentifier() override;
|
||||
bool isNewCardPresent() override;
|
||||
String getCardUid() override;
|
||||
void begin() override;
|
||||
void reset() override;
|
||||
void init() override;
|
||||
void end() override;
|
||||
};
|
|
@ -22,3 +22,8 @@ enum e_state {
|
|||
STATE_RESULT_FAILURE,
|
||||
STATE_RESULT_DISPLAY,
|
||||
};
|
||||
|
||||
enum e_scanstate {
|
||||
SCANSTATE_IDLE,
|
||||
SCANSTATE_ACTIVE,
|
||||
};
|
||||
|
|
|
@ -10,13 +10,21 @@
|
|||
#ifndef AFRAPAY_GIT_COMMIT
|
||||
#define AFRAPAY_GIT_COMMIT "unknown"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We're using an Az-Delivery ESP-32 Kit:
|
||||
* Product: https://web.archive.org/web/20230420182915/https://www.azdelivery.de/en/products/esp32-developmentboard
|
||||
* Pinout: https://web.archive.org/web/20210901112537/https://cdn.shopify.com/s/files/1/1509/1638/files/ESP-32_NodeMCU_Developmentboard_Pinout.pdf
|
||||
* Datasheet: https://web.archive.org/web/20221209154701/https://cdn.shopify.com/s/files/1/1509/1638/files/ESP-32_NodeMCU_Developmentboard_Schematic_korr.pdf?v=1666000508
|
||||
*/
|
||||
|
||||
//MFRC522 pinout (front) 3V3 RST GND IRQ MISO MOSI SCK SDA
|
||||
//MFRC522 pinout (rear) SDA SCK MOSI MISO IRQ GND RST 3V3
|
||||
#define PIN_HSPI_RST 4
|
||||
#define PIN_HSPI_MISO 12
|
||||
#define PIN_HSPI_MOSI 13
|
||||
#define PIN_HSPI_SCLK 14
|
||||
#define PIN_HSPI_SS 15
|
||||
#define PIN_HSPI_CS0 15 //CS0 (Chip Select 0) = SS channel 0
|
||||
#define PIN_HWSERIAL_RX 16
|
||||
#define PIN_HWSERIAL_TX 17
|
||||
#define PIN_BUZZER 19
|
||||
|
@ -26,3 +34,4 @@
|
|||
#define PIN_INTERRUPT_BALANCE 25
|
||||
#define PIN_INTERRUPT_LINK 33
|
||||
#define PIN_INTERRUPT_CANCEL 32
|
||||
#define PIN_INTERRUPT_IRQ_PN532 27
|
||||
|
|
|
@ -23,6 +23,7 @@ lib_deps =
|
|||
mcxiaoke/ESPDateTime@^1.0.4
|
||||
arduino12/rdm6300@^2.0.0
|
||||
bblanchon/ArduinoJson@^6.20.0
|
||||
adafruit/Adafruit PN532@^1.3.0
|
||||
check_tool = clangtidy
|
||||
check_flags =
|
||||
clangtidy: --config-file=.clang-tidy
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
#include <Arduino.h>
|
||||
#include <MFRC522.h>
|
||||
#include <rdm6300.h>
|
||||
#include "utils.h"
|
||||
#include "cardReader.h"
|
||||
|
||||
MFRC522CardReader::MFRC522CardReader(MFRC522* reader) {
|
||||
iReader = reader;
|
||||
}
|
||||
|
||||
bool MFRC522CardReader::isNewCardPresent() {
|
||||
return iReader->PICC_IsNewCardPresent() && iReader->PICC_ReadCardSerial();
|
||||
}
|
||||
|
||||
String MFRC522CardReader::getCardUid() {
|
||||
return byteArrayAsHexString(iReader->uid.uidByte, iReader->uid.size);
|
||||
}
|
||||
|
||||
void MFRC522CardReader::reset() {
|
||||
iReader->PCD_AntennaOff();
|
||||
iReader->PCD_Init();
|
||||
iReader->PCD_AntennaOn();
|
||||
}
|
||||
|
||||
inline bool MFRC522CardReader::canHaveUnstableIdentifier() {
|
||||
return true;
|
||||
}
|
||||
|
||||
RDM6300CardReader::RDM6300CardReader(Rdm6300* reader) {
|
||||
iReader = reader;
|
||||
}
|
||||
|
||||
bool RDM6300CardReader::isNewCardPresent() {
|
||||
return iReader->get_new_tag_id();
|
||||
}
|
||||
|
||||
String RDM6300CardReader::getCardUid() {
|
||||
auto uid = iReader->get_tag_id();
|
||||
char buf[16];
|
||||
sprintf(buf, "%010u", uid);
|
||||
return {buf};
|
||||
}
|
||||
|
||||
void RDM6300CardReader::reset() {
|
||||
/*
|
||||
* We don't need to do anything here
|
||||
* RDM6300 readers don't report a new card as present til the old card is removed and re-presented
|
||||
*/
|
||||
}
|
||||
|
||||
inline bool RDM6300CardReader::canHaveUnstableIdentifier() {
|
||||
// As far as I am aware, there are no 125khz tags with unstable identifiers
|
||||
return false;
|
||||
}
|
|
@ -6,40 +6,44 @@
|
|||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <SPI.h>
|
||||
#include <MFRC522.h>
|
||||
#include <ESPDateTime.h>
|
||||
#include <DateTimeTZ.h>
|
||||
#include <rdm6300.h>
|
||||
|
||||
#include "wifiFix.h"
|
||||
#include "pitches.h"
|
||||
#include "utils.h"
|
||||
#include "oled.h"
|
||||
#include "cardReader.h"
|
||||
#include "readers.h"
|
||||
#include "vars.h"
|
||||
|
||||
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
|
||||
MFRC522 mfrc522(PIN_HSPI_SS, PIN_HSPI_RST);
|
||||
OLED oled(U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, U8X8_PIN_NONE));
|
||||
WiFiClient* wifi = new WiFiClientFixed();
|
||||
HTTPClient* http = new HTTPClient();
|
||||
Rdm6300 rdm6300;
|
||||
|
||||
auto mfrc522reader = MFRC522CardReader(&mfrc522);
|
||||
auto rdm6300reader = RDM6300CardReader(&rdm6300);
|
||||
CardReader* readers[2] = {&mfrc522reader, &rdm6300reader};
|
||||
Reader* readers[] = {
|
||||
//new MFRC522CardReader(PIN_HSPI_SS, PIN_HSPI_RST),
|
||||
new PN532Reader(PIN_HSPI_SCLK, PIN_HSPI_MISO, PIN_HSPI_MOSI, PIN_HSPI_CS0),
|
||||
//new RDM6300Reader(PIN_HWSERIAL_RX)
|
||||
};
|
||||
|
||||
e_state state = STATE_IDLE;
|
||||
e_scanstate scanstate = SCANSTATE_IDLE;
|
||||
String apiUrl = "";
|
||||
const int gTimeout = 5000;
|
||||
const int scanTimeout = 15000;
|
||||
|
||||
CardReader* scannedCardReader;
|
||||
Reader* scannedCardReader;
|
||||
String scannedCardId = "";
|
||||
String lastStatusText = "";
|
||||
|
||||
|
||||
volatile bool interruptFired = false;
|
||||
unsigned long timer = 0;
|
||||
|
||||
void IRAM_ATTR PN532_IRQ() {
|
||||
PN532Reader::irq++;
|
||||
}
|
||||
|
||||
void IRAM_ATTR TransactInterruptHandler() {
|
||||
if (interruptFired || state != STATE_IDLE || digitalRead(PIN_INTERRUPT_TRANSACT)) {
|
||||
return;
|
||||
|
@ -73,28 +77,58 @@ void IRAM_ATTR CancelInterruptHandler() {
|
|||
bool cooldownCheck(long timeout) {
|
||||
if (millis() - timer > timeout) {
|
||||
state = STATE_IDLE;
|
||||
updateOLED(u8g2, state);
|
||||
oled.updateOLED(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateCardscan() {
|
||||
switch (state) {
|
||||
case STATE_TRANSACT_CARDSCAN:
|
||||
case STATE_LINK_CARD_SCAN:
|
||||
case STATE_LINK_CARD_RESCAN:
|
||||
case STATE_BALANCE_CARDSCAN:
|
||||
if (scanstate == SCANSTATE_ACTIVE)
|
||||
return;
|
||||
|
||||
for (Reader* reader : readers) {
|
||||
reader->begin();
|
||||
}
|
||||
scanstate = SCANSTATE_ACTIVE;
|
||||
break;
|
||||
case STATE_IDLE:
|
||||
case STATE_TRANSACT_VERIFY:
|
||||
case STATE_LINK_VERIFY:
|
||||
case STATE_BALANCE_VERIFY:
|
||||
case STATE_RESULT_SUCCESS:
|
||||
case STATE_RESULT_FAILURE:
|
||||
case STATE_RESULT_DISPLAY:
|
||||
if (scanstate == SCANSTATE_IDLE)
|
||||
return;
|
||||
|
||||
for (Reader* reader : readers) {
|
||||
reader->end();
|
||||
}
|
||||
scanstate = SCANSTATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
oled.begin();
|
||||
Serial2.begin(115200, SERIAL_8N1, PIN_HWSERIAL_RX, PIN_HWSERIAL_TX);
|
||||
SPI.begin(PIN_HSPI_SCLK, PIN_HSPI_MISO, PIN_HSPI_MOSI);
|
||||
|
||||
ledcSetup(0, 5000, 12);
|
||||
pinMode(PIN_INTERRUPT_IRQ_PN532, INPUT_PULLUP);
|
||||
pinMode(PIN_INTERRUPT_TRANSACT, INPUT_PULLUP);
|
||||
pinMode(PIN_INTERRUPT_BALANCE, INPUT_PULLUP);
|
||||
pinMode(PIN_INTERRUPT_CANCEL, INPUT_PULLUP);
|
||||
pinMode(PIN_INTERRUPT_LINK, INPUT_PULLUP);
|
||||
|
||||
u8g2.begin();
|
||||
drawLogo(u8g2, LOGO_MATECARD);
|
||||
u8g2.sendBuffer();
|
||||
|
||||
SPIFFS.begin(true);
|
||||
WiFiSettings.hostname = "afrapay-";
|
||||
apiUrl = WiFiSettings.string("AfRApay.Web API", "http://192.168.50.170:5296");
|
||||
|
@ -103,14 +137,15 @@ void setup() {
|
|||
else
|
||||
WiFiSettings.connect();
|
||||
|
||||
rdm6300.begin(PIN_HWSERIAL_RX);
|
||||
rdm6300.set_tag_timeout(65);
|
||||
mfrc522.PCD_Init();
|
||||
mfrc522.PCD_DumpVersionToSerial();
|
||||
for (Reader* reader : readers) {
|
||||
reader->init();
|
||||
}
|
||||
|
||||
DateTime.setTimeZone(TZ_Europe_Berlin);
|
||||
DateTime.begin();
|
||||
updateOLED(u8g2, state);
|
||||
oled.updateOLED(state);
|
||||
|
||||
attachInterrupt(PIN_INTERRUPT_IRQ_PN532, PN532_IRQ, FALLING);
|
||||
attachInterrupt(PIN_INTERRUPT_TRANSACT, TransactInterruptHandler, FALLING);
|
||||
attachInterrupt(PIN_INTERRUPT_BALANCE, BalanceInterruptHandler, FALLING);
|
||||
attachInterrupt(PIN_INTERRUPT_CANCEL, CancelInterruptHandler, FALLING);
|
||||
|
@ -119,13 +154,15 @@ void setup() {
|
|||
|
||||
void loop() {
|
||||
if (WiFiClass::status() != WL_CONNECTED) {
|
||||
updateOLED(u8g2, state, "WiFi disconnected :(");
|
||||
oled.updateOLED(state, "WiFi disconnected :(");
|
||||
state = STATE_IDLE;
|
||||
WiFi.reconnect();
|
||||
delay(50);
|
||||
return;
|
||||
}
|
||||
|
||||
updateCardscan();
|
||||
|
||||
if (interruptFired) {
|
||||
timer = millis();
|
||||
interruptFired = false;
|
||||
|
@ -133,10 +170,10 @@ void loop() {
|
|||
|
||||
switch (state) {
|
||||
case STATE_IDLE:
|
||||
updateOLED(u8g2, state);
|
||||
oled.updateOLED(state);
|
||||
break;
|
||||
case STATE_TRANSACT_CARDSCAN:
|
||||
for (CardReader* reader : readers) {
|
||||
for (Reader* reader : readers) {
|
||||
if (reader->isNewCardPresent()) {
|
||||
scannedCardId = reader->getCardUid();
|
||||
lastStatusText = "Card #" + scannedCardId;
|
||||
|
@ -146,11 +183,11 @@ void loop() {
|
|||
}
|
||||
}
|
||||
if (!cooldownCheck(scanTimeout)) {
|
||||
updateOLED(u8g2, state, String("1.50€"), String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
oled.updateOLED(state, String("1.50€"), String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
}
|
||||
break;
|
||||
case STATE_TRANSACT_VERIFY:
|
||||
updateOLED(u8g2, state, lastStatusText);
|
||||
oled.updateOLED(state, lastStatusText);
|
||||
tone(PIN_BUZZER, NOTE_A5, 25);
|
||||
tone(PIN_BUZZER, NOTE_NONE, 150);
|
||||
lastStatusText = cardTransaction(wifi, http, apiUrl, scannedCardId, "-150");
|
||||
|
@ -167,7 +204,7 @@ void loop() {
|
|||
timer = millis();
|
||||
return;
|
||||
case STATE_LINK_CARD_SCAN:
|
||||
for (CardReader* reader : readers) {
|
||||
for (Reader* reader : readers) {
|
||||
if (reader->isNewCardPresent()) {
|
||||
scannedCardReader = reader;
|
||||
scannedCardId = reader->getCardUid();
|
||||
|
@ -185,7 +222,7 @@ void loop() {
|
|||
}
|
||||
}
|
||||
if (!cooldownCheck(scanTimeout)) {
|
||||
updateOLED(u8g2, state, "Link", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
oled.updateOLED(state, "Link", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
}
|
||||
break;
|
||||
case STATE_LINK_CARD_RESCAN:
|
||||
|
@ -202,11 +239,11 @@ void loop() {
|
|||
}
|
||||
}
|
||||
if (!cooldownCheck(scanTimeout)) {
|
||||
updateOLED(u8g2, state, "Link - rescan", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
oled.updateOLED(state, "Link - rescan ", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
}
|
||||
break;
|
||||
case STATE_LINK_VERIFY:
|
||||
updateOLED(u8g2, state, lastStatusText);
|
||||
oled.updateOLED(state, lastStatusText);
|
||||
tone(PIN_BUZZER, NOTE_A5, 25);
|
||||
tone(PIN_BUZZER, NOTE_NONE, 150);
|
||||
lastStatusText = cardLink(wifi, http, apiUrl, scannedCardId);
|
||||
|
@ -225,7 +262,7 @@ void loop() {
|
|||
timer = millis();
|
||||
return;
|
||||
case STATE_BALANCE_CARDSCAN:
|
||||
for (CardReader* reader : readers) {
|
||||
for (Reader* reader : readers) {
|
||||
if (reader->isNewCardPresent()) {
|
||||
scannedCardId = reader->getCardUid();
|
||||
lastStatusText = "Card #" + scannedCardId;
|
||||
|
@ -234,11 +271,11 @@ void loop() {
|
|||
}
|
||||
}
|
||||
if (!cooldownCheck(scanTimeout)) {
|
||||
updateOLED(u8g2, state, "Balance", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
oled.updateOLED(state, "Balance", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||
}
|
||||
break;
|
||||
case STATE_BALANCE_VERIFY:
|
||||
updateOLED(u8g2, state, lastStatusText);
|
||||
oled.updateOLED(state, lastStatusText);
|
||||
tone(PIN_BUZZER, NOTE_A5, 25);
|
||||
tone(PIN_BUZZER, NOTE_NONE, 150);
|
||||
lastStatusText = cardBalance(wifi, http, apiUrl, scannedCardId);
|
||||
|
@ -261,7 +298,7 @@ void loop() {
|
|||
case STATE_RESULT_FAILURE:
|
||||
case STATE_RESULT_DISPLAY:
|
||||
if (!cooldownCheck(gTimeout)) {
|
||||
updateOLED(u8g2, state, lastStatusText, String(cooldownSecondsRemaining(gTimeout, timer)));
|
||||
oled.updateOLED(state, lastStatusText, String(cooldownSecondsRemaining(gTimeout, timer)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,38 @@
|
|||
#include <WiFi.h>
|
||||
#include <ESPDateTime.h>
|
||||
|
||||
#include <utility>
|
||||
#include "Arduino.h"
|
||||
#include "U8g2lib.h"
|
||||
#include "logos.h"
|
||||
#include "utils.h"
|
||||
#include "vars.h"
|
||||
#include "oled.h"
|
||||
|
||||
void drawCurvedLineV(U8G2 u8g2, int xStart, int yStart, int vert, int horiz) {
|
||||
OLED::OLED(U8G2 u8g2) {
|
||||
this->u8g2 = std::move(u8g2);
|
||||
}
|
||||
|
||||
void OLED::begin() {
|
||||
u8g2.begin();
|
||||
u8g2.setFont(u8g2_font_bpixel_te);
|
||||
u8g2_uint_t maxLength = 127 - u8g2.getUTF8Width("00:00:00 ");
|
||||
|
||||
if (u8g2.getUTF8Width(AFRAPAY_GIT_BRANCH "-" AFRAPAY_GIT_COMMIT) < maxLength) {
|
||||
revision = AFRAPAY_GIT_BRANCH "-" AFRAPAY_GIT_COMMIT;
|
||||
}
|
||||
else if (u8g2.getUTF8Width(AFRAPAY_GIT_BRANCH) < maxLength) {
|
||||
revision = AFRAPAY_GIT_BRANCH;
|
||||
}
|
||||
else if (u8g2.getUTF8Width(AFRAPAY_GIT_COMMIT) < maxLength) {
|
||||
revision = AFRAPAY_GIT_COMMIT;
|
||||
}
|
||||
|
||||
drawLogo(LOGO_MATECARD);
|
||||
u8g2.sendBuffer();
|
||||
}
|
||||
|
||||
void OLED::drawCurvedLineV(int xStart, int yStart, int vert, int horiz) {
|
||||
u8g2.drawVLine(xStart, yStart + 1, vert);
|
||||
u8g2.drawVLine(xStart + 1, yStart, vert);
|
||||
|
||||
|
@ -14,7 +40,7 @@ void drawCurvedLineV(U8G2 u8g2, int xStart, int yStart, int vert, int horiz) {
|
|||
u8g2.drawHLine(xStart + 1, yStart + vert + 1, horiz);
|
||||
}
|
||||
|
||||
void drawCurvedLine(U8G2 u8g2, int xStart, int yStart, int horiz, int vert) {
|
||||
void OLED::drawCurvedLine(int xStart, int yStart, int horiz, int vert) {
|
||||
u8g2.drawHLine(xStart, yStart, horiz);
|
||||
u8g2.drawHLine(xStart, yStart + 1, horiz);
|
||||
|
||||
|
@ -22,7 +48,7 @@ void drawCurvedLine(U8G2 u8g2, int xStart, int yStart, int horiz, int vert) {
|
|||
u8g2.drawVLine(xStart + horiz + 1, yStart + 1, vert);
|
||||
}
|
||||
|
||||
void drawLogoAfraPay(U8G2 u8g2) {
|
||||
void OLED::drawLogoAfraPay() {
|
||||
u8g2.setFontMode(1);
|
||||
u8g2.setFontDirection(0);
|
||||
|
||||
|
@ -39,42 +65,42 @@ void drawLogoAfraPay(U8G2 u8g2) {
|
|||
//u8g2.drawHLine(0, yOffset-12, xOffset);
|
||||
//u8g2.drawHLine(127-xOffset-1, yOffset, xOffset);
|
||||
|
||||
drawCurvedLineV(u8g2, xOffset + 69, yOffset, 7, 32);
|
||||
drawCurvedLine(u8g2, xOffset + 73, yOffset - 8, 28, 15);
|
||||
drawCurvedLineV(xOffset + 69, yOffset, 7, 32);
|
||||
drawCurvedLine(xOffset + 73, yOffset - 8, 28, 15);
|
||||
u8g2.drawPixel(xOffset + 101, yOffset + 7);
|
||||
}
|
||||
|
||||
void drawLogoBitmap(U8G2 u8g2, int width, int height, unsigned char bits[], int yOffset = 0) {
|
||||
void OLED::drawLogoBitmap(int width, int height, unsigned char bits[], int yOffset) {
|
||||
int offset = (128 - width) / 2;
|
||||
u8g2.drawXBM(offset, yOffset, width, height, bits);
|
||||
}
|
||||
|
||||
void drawLogo(U8G2 u8g2, e_logo logo) {
|
||||
void OLED::drawLogo(e_logo logo) {
|
||||
switch (logo) {
|
||||
case LOGO_AFRAPAY:
|
||||
drawLogoAfraPay(u8g2);
|
||||
drawLogoAfraPay();
|
||||
break;
|
||||
case LOGO_CONTACTLESS:
|
||||
drawLogoBitmap(u8g2, contactless_width, contactless_height, contactless_bits);
|
||||
drawLogoBitmap( contactless_width, contactless_height, contactless_bits);
|
||||
break;
|
||||
case LOGO_MATECARD:
|
||||
drawLogoBitmap(u8g2, matecard_width, matecard_height, matecard_bits, 5);
|
||||
drawLogoBitmap(matecard_width, matecard_height, matecard_bits, 5);
|
||||
u8g2.setFont(u8g2_font_bpixeldouble_tr);
|
||||
u8g2.drawStr((126 - u8g2.getStrWidth("matecard")) / 2, 57, "matecard");
|
||||
break;
|
||||
case LOGO_PENDING:
|
||||
drawLogoBitmap(u8g2, pending_width, pending_height, pending_bits, 5);
|
||||
drawLogoBitmap(pending_width, pending_height, pending_bits, 5);
|
||||
break;
|
||||
case LOGO_SUCCESS:
|
||||
drawLogoBitmap(u8g2, success_width, success_height, success_bits, 5);
|
||||
drawLogoBitmap(success_width, success_height, success_bits, 5);
|
||||
break;
|
||||
case LOGO_FAILURE:
|
||||
drawLogoBitmap(u8g2, failure_width, failure_height, failure_bits, 5);
|
||||
drawLogoBitmap(failure_width, failure_height, failure_bits, 5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void drawStatusText(U8G2 u8g2, const String& status, const String& statusRightAligned = "") {
|
||||
void OLED::drawStatusText(const String& status, const String& statusRightAligned) {
|
||||
u8g2.setFont(u8g2_font_bpixel_te);
|
||||
u8g2.drawUTF8(0, 61, status.c_str());
|
||||
|
||||
|
@ -84,52 +110,54 @@ void drawStatusText(U8G2 u8g2, const String& status, const String& statusRightAl
|
|||
}
|
||||
}
|
||||
|
||||
void drawFullScreenText(U8G2 u8g2, const String& textTop, const String& textBottom) {
|
||||
void OLED::drawFullScreenText(const String& textTop, const String& textBottom) {
|
||||
u8g2.setFont(u8g2_font_chargen_92_tr);
|
||||
u8g2.drawUTF8((127-u8g2.getUTF8Width(textTop.c_str()))/2, 13, textTop.c_str());
|
||||
u8g2.setFont(u8g2_font_maniac_te);
|
||||
u8g2.drawUTF8((127-u8g2.getUTF8Width(textBottom.c_str()))/2, 45, textBottom.c_str());
|
||||
}
|
||||
|
||||
void updateOLED(U8G2 u8g2, e_state state, const String& statusText, const String& statusTextRightAligned = "") {
|
||||
void OLED::updateOLED(e_state state, const String& statusText, const String& statusTextRightAligned) {
|
||||
u8g2.clearBuffer();
|
||||
|
||||
switch (state) {
|
||||
case STATE_IDLE:
|
||||
drawLogo(u8g2, LOGO_AFRAPAY);
|
||||
drawLogo(LOGO_AFRAPAY);
|
||||
break;
|
||||
case STATE_TRANSACT_CARDSCAN:
|
||||
case STATE_BALANCE_CARDSCAN:
|
||||
case STATE_LINK_CARD_SCAN:
|
||||
case STATE_LINK_CARD_RESCAN:
|
||||
drawLogo(u8g2, LOGO_CONTACTLESS);
|
||||
drawLogo(LOGO_CONTACTLESS);
|
||||
break;
|
||||
case STATE_RESULT_SUCCESS:
|
||||
drawLogo(u8g2, LOGO_SUCCESS);
|
||||
drawLogo(LOGO_SUCCESS);
|
||||
break;
|
||||
case STATE_RESULT_FAILURE:
|
||||
drawLogo(u8g2, LOGO_FAILURE);
|
||||
drawLogo(LOGO_FAILURE);
|
||||
break;
|
||||
case STATE_RESULT_DISPLAY:
|
||||
drawFullScreenText(u8g2, splitString(statusText, ':', 0), splitString(statusText, ':', 1) + "€");
|
||||
drawStatusText(u8g2, splitString(statusText, ':', 2), statusTextRightAligned);
|
||||
drawFullScreenText(splitString(statusText, ':', 0), splitString(statusText, ':', 1) + "€");
|
||||
drawStatusText(splitString(statusText, ':', 2), statusTextRightAligned);
|
||||
u8g2.sendBuffer();
|
||||
return;
|
||||
case STATE_TRANSACT_VERIFY:
|
||||
case STATE_BALANCE_VERIFY:
|
||||
case STATE_LINK_VERIFY:
|
||||
drawLogo(u8g2, LOGO_PENDING);
|
||||
drawLogo(LOGO_PENDING);
|
||||
break;
|
||||
}
|
||||
|
||||
drawStatusText(u8g2, statusText, statusTextRightAligned);
|
||||
drawStatusText(statusText, statusTextRightAligned);
|
||||
u8g2.sendBuffer();
|
||||
}
|
||||
|
||||
void updateOLED(const U8G2& u8g2, e_state state) {
|
||||
void OLED::updateOLED(e_state state) {
|
||||
String time = DateTime.format(DateFormatter::TIME_ONLY);
|
||||
if (!digitalRead(PIN_INTERRUPT_CANCEL) || millis()%20000 < 10000)
|
||||
updateOLED(u8g2, state, time, AFRAPAY_GIT_COMMIT);
|
||||
else
|
||||
updateOLED(u8g2, state, time, WiFi.localIP().toString());
|
||||
if (!digitalRead(PIN_INTERRUPT_CANCEL) || millis()%20000 < 10000) {
|
||||
updateOLED(state, time, revision);
|
||||
}
|
||||
else {
|
||||
updateOLED(state, time, WiFi.localIP().toString());
|
||||
}
|
||||
}
|
||||
|
|
31
AfRApay.MateCard/src/readers/mfrc522.cpp
Normal file
31
AfRApay.MateCard/src/readers/mfrc522.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <Arduino.h>
|
||||
#include "MFRC522.h"
|
||||
#include "utils.h"
|
||||
#include "readers.h"
|
||||
|
||||
MFRC522Reader::MFRC522Reader(byte chipSelectPin, byte resetPowerDownPin) {
|
||||
mfrc522 = new MFRC522(chipSelectPin, resetPowerDownPin);
|
||||
}
|
||||
|
||||
bool MFRC522Reader::isNewCardPresent() {
|
||||
return mfrc522->PICC_IsNewCardPresent() && mfrc522->PICC_ReadCardSerial();
|
||||
}
|
||||
|
||||
String MFRC522Reader::getCardUid() {
|
||||
return byteArrayAsHexString(mfrc522->uid.uidByte, mfrc522->uid.size);
|
||||
}
|
||||
|
||||
void MFRC522Reader::reset() {
|
||||
mfrc522->PCD_AntennaOff();
|
||||
mfrc522->PCD_Init();
|
||||
mfrc522->PCD_AntennaOn();
|
||||
}
|
||||
|
||||
inline bool MFRC522Reader::canHaveUnstableIdentifier() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MFRC522Reader::init() {
|
||||
mfrc522->PCD_Init();
|
||||
mfrc522->PCD_DumpVersionToSerial();
|
||||
}
|
53
AfRApay.MateCard/src/readers/pn532.cpp
Normal file
53
AfRApay.MateCard/src/readers/pn532.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include <Arduino.h>
|
||||
#include "utils.h"
|
||||
#include "readers.h"
|
||||
#include "vars.h"
|
||||
|
||||
volatile int PN532Reader::irq = 0;
|
||||
|
||||
PN532Reader::PN532Reader(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss) {
|
||||
pn532 = new Adafruit_PN532(clk, miso, mosi, ss);
|
||||
}
|
||||
|
||||
void PN532Reader::begin() {
|
||||
pn532->begin();
|
||||
irq = 0;
|
||||
pn532->startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A);
|
||||
}
|
||||
|
||||
void PN532Reader::end() {
|
||||
pn532->sendCommandCheckAck(new byte[1]{PN532_COMMAND_POWERDOWN}, 1, 1);
|
||||
}
|
||||
|
||||
bool PN532Reader::isNewCardPresent() {
|
||||
return irq > 1;
|
||||
}
|
||||
|
||||
String PN532Reader::getCardUid() {
|
||||
pn532->readDetectedPassiveTargetID(uid, &uidLength);
|
||||
Serial.println(byteArrayAsHexString(uid, uidLength));
|
||||
return byteArrayAsHexString(uid, uidLength);
|
||||
}
|
||||
|
||||
void PN532Reader::reset() {
|
||||
this->end();
|
||||
this->begin();
|
||||
}
|
||||
|
||||
inline bool PN532Reader::canHaveUnstableIdentifier() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PN532Reader::init() {
|
||||
pn532->begin();
|
||||
uint32_t version = pn532->getFirmwareVersion();
|
||||
if (!version) {
|
||||
Serial.print("Couldn't find PN53x board");
|
||||
return;
|
||||
//esp_restart();
|
||||
}
|
||||
|
||||
Serial.print("Found chip PN5"); Serial.println((version>>24) & 0xFF, HEX);
|
||||
Serial.print("Firmware ver. "); Serial.print((version>>16) & 0xFF, DEC);
|
||||
Serial.print('.'); Serial.println((version>>8) & 0xFF, DEC);
|
||||
}
|
37
AfRApay.MateCard/src/readers/rdm6300.cpp
Normal file
37
AfRApay.MateCard/src/readers/rdm6300.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <Arduino.h>
|
||||
#include "rdm6300.h"
|
||||
#include "utils.h"
|
||||
#include "readers.h"
|
||||
|
||||
RDM6300Reader::RDM6300Reader(int pin) {
|
||||
this->pin = pin;
|
||||
rdm6300 = new Rdm6300;
|
||||
}
|
||||
|
||||
bool RDM6300Reader::isNewCardPresent() {
|
||||
return rdm6300->get_new_tag_id();
|
||||
}
|
||||
|
||||
String RDM6300Reader::getCardUid() {
|
||||
auto uid = rdm6300->get_tag_id();
|
||||
char buf[16];
|
||||
sprintf(buf, "%010u", uid);
|
||||
return {buf};
|
||||
}
|
||||
|
||||
void RDM6300Reader::reset() {
|
||||
/*
|
||||
* We don't need to do anything here
|
||||
* RDM6300 readers don't report a new card as present til the old card is removed and re-presented
|
||||
*/
|
||||
}
|
||||
|
||||
inline bool RDM6300Reader::canHaveUnstableIdentifier() {
|
||||
// As far as I am aware, there are no 125khz tags with unstable identifiers
|
||||
return false;
|
||||
}
|
||||
|
||||
void RDM6300Reader::init() {
|
||||
rdm6300->begin(pin);
|
||||
rdm6300->set_tag_timeout(65);
|
||||
}
|
Loading…
Reference in a new issue