Skip to content

Commit

Permalink
Replaced READER/WRITER with CONTROLLER/EMULATOR throughout and added …
Browse files Browse the repository at this point in the history
…keypad emulation

information to README (cf. #4)
  • Loading branch information
twystd committed Oct 25, 2023
1 parent aec5570 commit 06fb5af
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 61 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,43 @@ GPIO7 and GPIO8 by default):
JUMPER_WRITE is pulled LOW
- if both JUMPER_READ and JUMPER_WRITE are pulled LOW the operating mode is UNKNOWN.

## Keypad emulation

The code supports two keypad modes:
- 4-bit burst mode
- 8-bit burst mode

In 4 bit burst mode, each keypress is sent as 4 bit code followed by a 28-bit 'space', with keypad digits encoded as follows:

| Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * | # |
|-------|------|------|------|------|------|------|------|------|------|------|------|------|
| Code | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 |

In 8 bit burst mode, each keypress is sent as 8 bit code followed by a 24-bit 'space', with keypad digits encoded as follows:

| Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * | # |
|-------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|
| Code | 11110000 | 11100001 | 11010010 | 11000011 | 10110100 | 10100101 | 10010110 | 10000111 | 01111000 | 01101001 | 01011010 | 01001011 |

- In _emulator_ operating mode, the keypad mode is set by the `KEYPAD` build constant ('4-bit' or '8-bit')
- In _controller_ operating mode the keypad reader can detect and read both keypad encodings. A keycode is terminated by either a
'#' or a 12.5 second timeout.


## Supervisor passcodes

The supervisor passcodes are _controller_ operating mode override codes that unconditionally unlocks the door.

The _controller_ operating mode supports up to four user-defined passcodes which can be set (or cleared) using the
_PASSCODES_ command in the CLI. The passcodes may be up to 6 digits in length.


## Master passcode

In addition to the supervisor passcodes, the _controller_ operating mode provides for a MASTER override code that
unconditionally unlocks the door. The _MASTER_ override code is set at build time via the `MASTER_PASSCODE` build constant.


## Build constants

The _build constants_ in the _Makefiles_ define the initial operational settings:
Expand Down
27 changes: 14 additions & 13 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- (?) Make -Wimplicit-function-declaration an error

- [x] Weird card after ACL revoking a card in the middle of a list
- [x] clear ACL
- [x] Clear ACL

- [ ] Emulate keypad (cf. https://github.com/uhppoted/uhppoted-wiegand/issues/4)
- [x] 4-bit burst mode write
Expand All @@ -14,20 +14,21 @@
- [x] card + PIN writer
- [x] FIXME in acl.c
- [x] card + PIN read
- [x] timeout on keycode
- [x] rework ACL as struct (with cards, timer, etc)
- [x] Update all variants
- [x] controller
- [x] universal
- [x] Remove debug stuff
- [ ] Check mode == CONTROLLER/READER in unlock, etc
- [ ] README
- [x] CHANGELOG
- [x] Check mode == CONTROLLER/READER
- [x] unlock
- [x] door sensor emulation
- [x] pushbutton emulation
= [x] LEDs
- [x] Replace READER with CONTROLLER
- [x] Replace WRITER with EMULATOR
- [x] README
- [x] build constants
- [x] _operating modes_
- [ ] keypad modes
- [ ] passcodes
- [ ] master passcode
- [x] CHANGELOG
- [x] keypad modes
- [x] passcodes
- [x] master passcode
- [ ] Restructure emulator CLI

- [ ] PicoW+TCP/IP
- [ ] Figure out SD card detect interrupt conflict
Expand Down
Binary file added documentation/KeypadMode_REF.pdf
Binary file not shown.
6 changes: 2 additions & 4 deletions pico/core/include/wiegand.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ extern const enum pio_interrupt_source IRQ_READER;

enum MODE {
UNKNOWN = 0,
READER = 1,
WRITER = 2,
EMULATOR = 3,
CONTROLLER = 4,
CONTROLLER = 1,
EMULATOR = 2,
INDETERMINATE = 0xff
};

Expand Down
6 changes: 3 additions & 3 deletions pico/core/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void cli_blink(txrx f, void *context) {
*
*/
void cli_unlock_door(txrx f, void *context) {
if ((mode == READER) || (mode == CONTROLLER)) {
if (mode == CONTROLLER) {
door_unlock(5000);
}
}
Expand Down Expand Up @@ -308,7 +308,7 @@ void cli_swipe(char *cmd, txrx f, void *context) {
}
}

if ((mode == WRITER) || (mode == EMULATOR)) {
if (mode == EMULATOR) {
if ((code = strtok(NULL, " ,")) == NULL) {
write_card(facility_code, card);
f(context, "CARD WRITE OK");
Expand All @@ -331,7 +331,7 @@ void cli_swipe(char *cmd, txrx f, void *context) {
void keypad(char *cmd, txrx f, void *context) {
int N = strlen(cmd);

if (((mode == WRITER) || (mode == EMULATOR)) && N > 0) {
if ((mode == EMULATOR) && N > 0) {
char s[64];

for (int i = 0; i < N; i++) {
Expand Down
6 changes: 3 additions & 3 deletions pico/core/src/led.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ bool callback(repeating_timer_t *rt) {

/* Initialises the PIO for the emulator LED input and the reader LED
* output. The PIO is only initialised with the reader LED output
* program if the mode is READER or CONTROLLER.
* program if the mode is CONTROLLER.
*
*/
bool led_initialise(enum MODE mode) {
Expand Down Expand Up @@ -178,8 +178,8 @@ bool led_initialise(enum MODE mode) {
ok = false;
}

// ... initialise READER LED
if ((mode == READER) || (mode == CONTROLLER)) {
// ... initialise reader LED
if (mode == CONTROLLER) {
queue_init(&BLINK_STATE.queue, sizeof(int32_t), 16);

if (add_repeating_timer_ms(100, blink_callback, NULL, &BLINK_STATE.timer)) {
Expand Down
25 changes: 9 additions & 16 deletions pico/core/src/relays.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int64_t relay_timeout(alarm_id_t, void *);
bool relay_initialise(enum MODE mode) {
static repeating_timer_t relay_rt;

if ((mode == READER) || (mode == CONTROLLER)) {
if (mode == CONTROLLER) {
TPIC_set(DOOR_UNLOCK, false);
}

Expand Down Expand Up @@ -181,47 +181,40 @@ void relay_event(uint32_t v) {
}
}

/* Sets the DOOR OPEN relay (READER/CONTROLLER mode only).
/* Sets the DOOR OPEN relay (CONTROLLER mode only).
*
*/
void door_unlock(uint32_t delay) {
if ((mode == READER) || (mode == CONTROLLER)) {
if (mode == CONTROLLER) {
if (add_alarm_in_ms(delay, relay_timeout, NULL, false) > 0) {
TPIC_set(DOOR_UNLOCK, true);
}
}
}

/* Releases the DOOR UNLOCK relay.
*
*/
void relay_close() {
TPIC_set(DOOR_UNLOCK, false);
}

/* Sets/clears the DOOR CONTACT emulation relay (WRITER/EMULATOR mode only).
/* Sets/clears the DOOR CONTACT emulation relay (EMULATOR mode only).
*
*/
void relay_door_contact(bool closed) {
if ((mode == WRITER) || (mode == EMULATOR)) {
if (mode == EMULATOR) {
TPIC_set(DOOR_CONTACT, closed);
}
}

/* Sets/clears the PUSHBUTTON emulation relay (WRITER mode only).
/* Sets/clears the PUSHBUTTON emulation relay (EMULATOR mode only).
*
*/
void relay_pushbutton(bool closed) {
if ((mode == WRITER) || (mode == EMULATOR)) {
if (mode == EMULATOR) {
TPIC_set(PUSHBUTTON, closed);
}
}

/* Timeout handler. Clears the DOOR OPEN relay.
/* Timeout handler. Clears the DOOR UNLOCK relay.
*
*/
int64_t relay_timeout(alarm_id_t id, void *data) {
relay_close();
TPIC_set(DOOR_UNLOCK, false);
return 0;
}

Expand Down
7 changes: 2 additions & 5 deletions pico/core/src/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@

const char *MODES[] = {
"UNKNOWN",
"READER",
"WRITE",
"EMULATOR",
"CONTROLLER",
};
"EMULATOR"};

void sys_start() {
char s[64];
Expand All @@ -40,7 +37,7 @@ void sys_start() {
void sys_ok() {
char s[64];

if (mode <= CONTROLLER) {
if (mode <= EMULATOR) {
snprintf(s, sizeof(s), "%-6s %-8s %s", "SYS", MODES[mode], "OK");
} else {
snprintf(s, sizeof(s), "%-6s %-8s %s", "SYS", "???", "OK");
Expand Down
4 changes: 2 additions & 2 deletions pico/universal/common/src/universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void dispatch(uint32_t v) {
if ((v & MSG) == MSG_CARD) {
on_card_read(v & 0x0fffffff);

if (last_card.ok && mode == READER) {
if (last_card.ok && mode == CONTROLLER) {
enum ACCESS access = acl_allowed(last_card.facility_code, last_card.card_number, "");

switch (access) {
Expand Down Expand Up @@ -47,7 +47,7 @@ void dispatch(uint32_t v) {
char *b = (char *)(SRAM_BASE | (v & 0x0fffffff));
enum ACCESS access;

if (mode == READER) {
if (mode == CONTROLLER) {
if (last_card.ok && last_card.access == NEEDS_PIN) {
if ((access = acl_allowed(last_card.facility_code, last_card.card_number, b)) == GRANTED) {
last_card.access = GRANTED;
Expand Down
6 changes: 3 additions & 3 deletions pico/universal/pico/base/src/universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ void sysinit() {
puts(" Pico-Wiegand Universal Interface");

if (!gpio_get(JUMPER_READ) && gpio_get(JUMPER_WRITE)) {
mode = READER;
mode = CONTROLLER;
} else if (gpio_get(JUMPER_READ) && !gpio_get(JUMPER_WRITE)) {
mode = WRITER;
mode = EMULATOR;
} else {
mode = UNKNOWN;
}
Expand All @@ -203,7 +203,7 @@ void sysinit() {
}

// ... set door contact to 'CLOSED'
if (mode == WRITER) {
if (mode == EMULATOR) {
relay_door_contact(true);
}

Expand Down
6 changes: 3 additions & 3 deletions pico/universal/pico/usb/src/universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ void sysinit() {
puts(" Pico-Wiegand Universal Interface");

if (!gpio_get(JUMPER_READ) && gpio_get(JUMPER_WRITE)) {
mode = READER;
mode = CONTROLLER;
} else if (gpio_get(JUMPER_READ) && !gpio_get(JUMPER_WRITE)) {
mode = WRITER;
mode = EMULATOR;
} else {
mode = UNKNOWN;
}
Expand All @@ -204,7 +204,7 @@ void sysinit() {
}

// ... set door contact to 'CLOSED'
if (mode == WRITER) {
if (mode == EMULATOR) {
relay_door_contact(true);
}

Expand Down
6 changes: 3 additions & 3 deletions pico/universal/picow/base/src/universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,9 @@ void sysinit() {
puts(" PicoW-Wiegand Universal Interface");

if (!gpio_get(JUMPER_READ) && gpio_get(JUMPER_WRITE)) {
mode = READER;
mode = CONTROLLER;
} else if (gpio_get(JUMPER_READ) && !gpio_get(JUMPER_WRITE)) {
mode = WRITER;
mode = EMULATOR;
} else {
mode = UNKNOWN;
}
Expand All @@ -207,7 +207,7 @@ void sysinit() {
}

// ... set door contact to 'CLOSED'
if (mode == WRITER) {
if (mode == EMULATOR) {
relay_door_contact(true);
}

Expand Down
6 changes: 3 additions & 3 deletions pico/universal/picow/wifi+usb/src/universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ void sysinit() {
puts(" PicoW-Wiegand Universal Interface (WiFi+USB)");

if (!gpio_get(JUMPER_READ) && gpio_get(JUMPER_WRITE)) {
mode = READER;
mode = CONTROLLER;
} else if (gpio_get(JUMPER_READ) && !gpio_get(JUMPER_WRITE)) {
mode = WRITER;
mode = EMULATOR;
} else {
mode = UNKNOWN;
}
Expand All @@ -218,7 +218,7 @@ void sysinit() {
}

// ... set door contact to 'CLOSED'
if (mode == WRITER) {
if (mode == EMULATOR) {
relay_door_contact(true);
}

Expand Down
6 changes: 3 additions & 3 deletions pico/universal/picow/wifi/src/universal.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ void sysinit() {
puts(" PicoW-Wiegand Universal Interface (WiFi)");

if (!gpio_get(JUMPER_READ) && gpio_get(JUMPER_WRITE)) {
mode = READER;
mode = CONTROLLER;
} else if (gpio_get(JUMPER_READ) && !gpio_get(JUMPER_WRITE)) {
mode = WRITER;
mode = EMULATOR;
} else {
mode = UNKNOWN;
}
Expand All @@ -216,7 +216,7 @@ void sysinit() {
}

// ... set door contact to 'CLOSED'
if (mode == WRITER) {
if (mode == EMULATOR) {
relay_door_contact(true);
}

Expand Down

0 comments on commit 06fb5af

Please sign in to comment.