Skip to content

Commit

Permalink
Emulate CRP-1231BR-10
Browse files Browse the repository at this point in the history
Co-authored-by: tugpoat <[email protected]>
  • Loading branch information
GXTX and tugpoat committed Feb 9, 2023
1 parent 97753e7 commit 6658ba9
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 11 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_executable(${PROJECT_NAME}
Includes/CardIo.cpp
Includes/SerIo.cpp
Includes/C1231LR.cpp
Includes/C1231BR.cpp
Includes/base64.cpp
Includes/WebIo.cpp
)
Expand Down
157 changes: 157 additions & 0 deletions Includes/C1231BR.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
YACardEmu
----------------
Copyright (C) 2020-2023 wutno (https://github.com/GXTX)
Copyright (C) 2022-2023 tugpoat (https://github.com/tugpoat)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "C1231BR.h"

C1231BR::C1231BR(CardIo::Settings* settings) : CardIo(settings)
{
}

void C1231BR::UpdateRStatus()
{
// We "grab" the card for the user
if (localStatus.position == CardPosition::POS_IN_FRONT) {
m_cardSettings->insertedCard = false;
MoveCard(MovePositions::NO_CARD);
}

// We require the user to "insert" a card if we're waiting
if (m_cardSettings->insertedCard && localStatus.position == CardPosition::NO_CARD) {
MoveCard(MovePositions::READ_WRITE_HEAD);

if (runningCommand && status.s == S::WAITING_FOR_CARD) {
// Make sure the user can actually insert a card
localStatus.shutter = true;
status.s = S::RUNNING_COMMAND;
}
}
}

bool C1231BR::HasCard()
{
return localStatus.position != CardPosition::NO_CARD;
}

void C1231BR::DispenseCard()
{
localStatus.position = CardPosition::POS_THERM_DISP;
}

void C1231BR::EjectCard()
{
if (localStatus.position != CardPosition::NO_CARD) {
localStatus.shutter = true;
localStatus.position = CardPosition::POS_IN_FRONT;
}
}

uint8_t C1231BR::GetRStatus()
{
return localStatus.GetByte();
}

void C1231BR::Command_10_Initalize()
{
enum Mode {
Standard = 0x30, // We actually eject anyway..
EjectAfter = 0x31,
ResetSpecifications = 0x32,
};

Mode mode = static_cast<Mode>(currentPacket[0]);

switch (currentStep) {
case 1:
if (mode == Mode::EjectAfter) {
localStatus.shutter = true;
}
if (HasCard()) {
EjectCard();
}
break;
default:
break;
}

if (currentStep > 1) {
runningCommand = false;
}
}

void C1231BR::Command_D0_ShutterControl()
{
// Only actions are to close and open the shutter
enum Action {
Close = 0x30,
Open = 0x31,
};

Action action = static_cast<Action>(currentPacket[0]);

if (action == Action::Open) {
localStatus.shutter = true;
} else {
localStatus.shutter = false;
}

runningCommand = false;
}

void C1231BR::MoveCard(CardIo::MovePositions position)
{
switch (position) {
case MovePositions::NO_CARD:
localStatus.position = CardPosition::NO_CARD;
break;
case MovePositions::READ_WRITE_HEAD:
localStatus.position = CardPosition::POS_MAG;
break;
case MovePositions::THERMAL_HEAD:
localStatus.position = CardPosition::POS_THERM;
break;
case MovePositions::DISPENSER_THERMAL:
localStatus.position = CardPosition::POS_THERM_DISP;
break;
case MovePositions::EJECT:
localStatus.position = CardPosition::POS_IN_FRONT;
break;
default: break;
}
}

CardIo::MovePositions C1231BR::GetCardPos()
{
switch (localStatus.position) {
case CardPosition::NO_CARD:
return MovePositions::NO_CARD;
case CardPosition::POS_MAG:
return MovePositions::READ_WRITE_HEAD;
case CardPosition::POS_THERM:
return MovePositions::THERMAL_HEAD;
case CardPosition::POS_THERM_DISP:
return MovePositions::DISPENSER_THERMAL;
case CardPosition::POS_IN_FRONT:
return MovePositions::EJECT;
default:
return MovePositions::NO_CARD;
}
}
72 changes: 72 additions & 0 deletions Includes/C1231BR.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
YACardEmu
----------------
Copyright (C) 2020-2023 wutno (https://github.com/GXTX)
Copyright (C) 2022-2023 tugpoat (https://github.com/tugpoat)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef C1231BR_H
#define C1231BR_H

#include <atomic>
#include <ctime>
#include <fstream>
#include <iostream>
#include <vector>

#include "CardIo.h"

class C1231BR : public CardIo {
public:
C1231BR(CardIo::Settings* settings);

protected:
enum class CardPosition {
NO_CARD = 0b00000,
POS_MAG = 0b11000,
POS_THERM = 0b00111,
POS_THERM_DISP = 0b11100,
POS_IN_FRONT = 0b00001,
};

struct LocalStatus {
bool shutter = true;
bool dispenser = true; // report full dispenser
CardPosition position = CardPosition::NO_CARD;

uint8_t GetByte()
{
return 1 << (shutter ? 7 : 6) | (dispenser ? 1 : 0) << 5 | static_cast<uint8_t>(position);
}
};

LocalStatus localStatus{};
bool HasCard() override;
void DispenseCard() override;
void EjectCard() override;
void UpdateRStatus() override;
uint8_t GetRStatus() override;

void Command_10_Initalize() override;
void Command_D0_ShutterControl() override;

void MoveCard(CardIo::MovePositions position) override;
CardIo::MovePositions GetCardPos() override;
};

#endif // C1231BR
16 changes: 8 additions & 8 deletions Includes/C1231LR.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ class C1231LR : public CardIo
};

CardPosition localStatus{CardPosition::NO_CARD};
bool HasCard();
void DispenseCard();
void EjectCard();
void UpdateRStatus();
uint8_t GetRStatus();

void MoveCard(CardIo::MovePositions position);
CardIo::MovePositions GetCardPos();
bool HasCard() override;
void DispenseCard() override;
void EjectCard() override;
void UpdateRStatus() override;
uint8_t GetRStatus() override;

void MoveCard(CardIo::MovePositions position) override;
CardIo::MovePositions GetCardPos() override;
};

#endif //C1231LR
7 changes: 7 additions & 0 deletions Includes/CardIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,12 @@ void CardIo::Command_C1_SetRetry()
runningCommand = false;
}

void CardIo::Command_D0_ShutterControl()
{
// Only BR model supports this command
SetSError(S::ILLEGAL_COMMAND);
}

void CardIo::Command_E1_SetRTC()
{
std::stringstream timeStrS{};
Expand Down Expand Up @@ -738,6 +744,7 @@ void CardIo::HandlePacket()
case 0xB0: Command_B0_DispenseCardS31(); break;
case 0xC0: Command_C0_ControlLED(); break;
case 0xC1: Command_C1_SetRetry(); break;
case 0xD0: Command_D0_ShutterControl(); break;
case 0xE1: Command_E1_SetRTC(); break;
case 0xF0: Command_F0_GetVersion(); break;
case 0xF1: Command_F1_GetRTC(); break;
Expand Down
4 changes: 3 additions & 1 deletion Includes/CardIo.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class CardIo
};

CardIo(CardIo::Settings *settings);
virtual ~CardIo() = default;
CardIo::StatusCode BuildPacket(std::vector<uint8_t> &readBuffer);
CardIo::StatusCode ReceivePacket(std::vector<uint8_t> &writeBuffer);

Expand Down Expand Up @@ -147,7 +148,7 @@ class CardIo
void WriteTrack(std::vector<uint8_t> &trackData, int trackNumber);

// Commands
void Command_10_Initalize();
virtual void Command_10_Initalize();
void Command_20_ReadStatus();
void Command_33_ReadData2(); // multi-track read
void Command_35_GetData(); // Spit out the entire card
Expand All @@ -164,6 +165,7 @@ class CardIo
void Command_B0_DispenseCardS31();
void Command_C0_ControlLED();
void Command_C1_SetRetry();
virtual void Command_D0_ShutterControl();
void Command_E1_SetRTC();
void Command_F0_GetVersion();
void Command_F1_GetRTC();
Expand Down
3 changes: 3 additions & 0 deletions config.ini.sample
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ basepath = /home/wutno/cards/
; Windows
;serialpath = COM3
;serialpath = \\.\pipe\YACardEmu
; Which device should we emulate?
; C1231LR / C1231BR
targetdevice = C1231LR
;
; Optional
;
Expand Down
14 changes: 12 additions & 2 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <string>

#include "C1231LR.h"
#include "C1231BR.h"
#include "SerIo.h"
#include "WebIo.h"

Expand Down Expand Up @@ -70,6 +71,7 @@ bool ReadConfig()
lport = ini["config"]["apiport"];
lbaud = ini["config"]["serialbaud"];
lparity = ini["config"]["serialparity"];
globalSettings.card.mech = ini["config"]["targetdevice"];
globalSettings.card.cardPath = ini["config"]["basepath"];
globalSettings.card.cardName = ini["config"]["autoselectedcard"];
globalSettings.serial.devicePath = ini["config"]["serialpath"];
Expand Down Expand Up @@ -126,6 +128,16 @@ int main()
return 1;
}

std::unique_ptr<CardIo> cardHandler{};
if (globalSettings.card.mech.compare("C1231LR") == 0) {
cardHandler = std::make_unique<C1231LR>(&globalSettings.card);
} else if (globalSettings.card.mech.compare("C1231BR") == 0) {
cardHandler = std::make_unique<C1231BR>(&globalSettings.card);
} else {
spdlog::critical("Invalid target device: {}", globalSettings.card.mech);
return 1;
}

std::unique_ptr<SerIo> serialHandler = std::make_unique<SerIo>(&globalSettings.serial);
if (!serialHandler->Open()) {
return 1;
Expand All @@ -135,8 +147,6 @@ int main()
std::unique_ptr<WebIo> webHandler = std::make_unique<WebIo>(&globalSettings.card, globalSettings.webPort, &running);
webHandler->Spawn();

std::unique_ptr<C1231LR> cardHandler = std::make_unique<C1231LR>(&globalSettings.card);

// TODO: These don't need to be here, put them in their respective classes
SerIo::Status serialStatus = SerIo::Status::Okay;
CardIo::StatusCode cardStatus = CardIo::StatusCode::Okay;
Expand Down

0 comments on commit 6658ba9

Please sign in to comment.