Commit 15bc246c authored by Bc. Petr Elexa's avatar Bc. Petr Elexa

Make tag reading interrupt driven

parent 43b14b12
......@@ -13,16 +13,16 @@
#define DEVEL_BOARD
//Use global UID from chip as terminal unique ID
// Use global UID from chip as terminal unique ID
#define IAP_READ_UID 58
extern unsigned int TERMINAL_UID[4];
extern unsigned int TERMINAL_UID[4]; // 0 is least significant word
//---------------------------------------------------------------------------------------------------------------------
//Default values for door 0
// Values for door 0
//---------------------------------------------------------------------------------------------------------------------
#define DOOR_0_ACC_PANEL_ON false
#define DOOR_0_ACC_PANEL_PORT 1
#define DOOR_0_ACC_PANEL_PORT 1 // Port must be unique for each access panel (reader)
#define DOOR_0_ACC_PANEL_D0_PIN 1
#define DOOR_0_ACC_PANEL_D1_PIN 2
#define DOOR_0_ACC_PANEL_BEEP_PORT 0
......@@ -32,31 +32,31 @@ extern unsigned int TERMINAL_UID[4];
#define DOOR_0_RELAY_PORT 0
#define DOOR_0_RELAY_PIN 0
#define DOOR_0_OPEN_TIME_MS 5000
#define DOOR_0_OPEN_TIME_MS 3000
//---------------------------------------------------------------------------------------------------------------------
//Default values for door 1
// Values for door 1
//---------------------------------------------------------------------------------------------------------------------
#define DOOR_1_ACC_PANEL_ON false
#define DOOR_1_ACC_PANEL_ON true
#define DOOR_1_ACC_PANEL_PORT 2
#define DOOR_1_ACC_PANEL_D0_PIN 0
#define DOOR_1_ACC_PANEL_D1_PIN 0
#define DOOR_1_ACC_PANEL_BEEP_PORT 0
#define DOOR_1_ACC_PANEL_BEEP_PIN 0
#define DOOR_1_ACC_PANEL_GLED_PORT 0
#define DOOR_1_ACC_PANEL_GLED_PIN 0
#define DOOR_1_ACC_PANEL_PORT 2 // Port must be unique for each access panel (reader)
#define DOOR_1_ACC_PANEL_D0_PIN 7
#define DOOR_1_ACC_PANEL_D1_PIN 8
#define DOOR_1_ACC_PANEL_BEEP_PORT 2
#define DOOR_1_ACC_PANEL_BEEP_PIN 3
#define DOOR_1_ACC_PANEL_GLED_PORT 2
#define DOOR_1_ACC_PANEL_GLED_PIN 6
#define DOOR_1_RELAY_PORT 0
#define DOOR_1_RELAY_PIN 0
#define DOOR_1_OPEN_TIME_MS 5000
#define DOOR_1_RELAY_PORT 2
#define DOOR_1_RELAY_PIN 10
#define DOOR_1_OPEN_TIME_MS 2000
//---------------------------------------------------------------------------------------------------------------------
//Default values for door 2
// Values for door 2
//---------------------------------------------------------------------------------------------------------------------
#define DOOR_2_ACC_PANEL_ON true
#define DOOR_2_ACC_PANEL_PORT 3
#define DOOR_2_ACC_PANEL_PORT 3 // Port must be unique for each access panel (reader)
#define DOOR_2_ACC_PANEL_D0_PIN 1
#define DOOR_2_ACC_PANEL_D1_PIN 2
#define DOOR_2_ACC_PANEL_BEEP_PORT 2
......@@ -66,13 +66,17 @@ extern unsigned int TERMINAL_UID[4];
#define DOOR_2_RELAY_PORT 2
#define DOOR_2_RELAY_PIN 2
#define DOOR_2_OPEN_TIME_MS 5000
#define DOOR_2_OPEN_TIME_MS 2000
//---------------------------------------------------------------------------------------------------------------------
#define BEEP_ON_SUCCESS true
#define OK_LED_ON_SUCCESS true
#define WEIGAND_DEVICE_LIMIT 3
#define WEIGAND_DEVICE_LIMIT 4
#define SERIAL_DEVICE_LIMIT 0
#define DOOR_ACC_PANEL_MAX_COUNT (WEIGAND_DEVICE_LIMIT + SERIAL_DEVICE_LIMIT)
// IO
#define LOG_HIGH 1
#define LOG_LOW 0
......
#include "panel.h"
static StreamBufferHandle_t _reader_buffer;
static void panel_timer_callback(TimerHandle_t pxTimer)
{
configASSERT(pxTimer);
......@@ -16,30 +18,34 @@ static void panel_timer_callback(TimerHandle_t pxTimer)
void panel_init(uint8_t id)
{
//Create stream buffer
acc_panel[id].card_stream = xStreamBufferCreate(CONSUMER_BUFF_SIZE, CONSUMER_BUFF_SIZE);
configASSERT(acc_panel[id].card_stream);
//Create stream buffer to receive id from all card readers
if (_reader_buffer == NULL)
{
_reader_buffer = xStreamBufferCreate(WEIGAND_DEVICE_LIMIT * WEIGAND26_BUFF_ITEM_SIZE, WEIGAND26_BUFF_ITEM_SIZE);
}
configASSERT(_reader_buffer);
//Init interface to reader
weigand_init(acc_panel[id].card_stream, acc_panel[id].acc_panel_port, acc_panel[id].acc_panel_d0_pin, acc_panel[id].acc_panel_d1_pin);
weigand_init(_reader_buffer, id, acc_panel[id].acc_panel_port, acc_panel[id].acc_panel_d0_pin, acc_panel[id].acc_panel_d1_pin);
//Create timer
if (acc_panel[id].timer == NULL)
{
acc_panel[id].timer = xTimerCreate("PNL_TMR", (acc_panel[id].open_time_sec / portTICK_PERIOD_MS), pdFALSE, (void *)(uint32_t) id, panel_timer_callback);
acc_panel[id].timer = xTimerCreate("PNL", (acc_panel[id].open_time_sec / portTICK_PERIOD_MS), pdFALSE, (void *)(uint32_t) id, panel_timer_callback);
}
configASSERT(acc_panel[id].timer);
//Setup LED
Chip_GPIO_SetPinDIROutput(LPC_GPIO, acc_panel[id].acc_panel_gled_port, acc_panel[id].acc_panel_gled_pin);
Chip_IOCON_PinMux(LPC_IOCON, CHIP_IOCON_PIO[acc_panel[id].acc_panel_gled_port][acc_panel[id].acc_panel_gled_pin], IOCON_MODE_PULLUP, IOCON_FUNC0);
Chip_IOCON_PinMux(LPC_IOCON, CHIP_IOCON_PIO[acc_panel[id].acc_panel_gled_port][acc_panel[id].acc_panel_gled_pin], IOCON_MODE_INACT, IOCON_FUNC0);
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].acc_panel_gled_port, acc_panel[id].acc_panel_gled_pin, LOG_HIGH);
//Setup BEEPER
Chip_GPIO_SetPinDIROutput(LPC_GPIO, acc_panel[id].acc_panel_beep_port, acc_panel[id].acc_panel_beep_pin);
Chip_IOCON_PinMux(LPC_IOCON, CHIP_IOCON_PIO[acc_panel[id].acc_panel_beep_port][acc_panel[id].acc_panel_beep_pin], IOCON_MODE_PULLUP, IOCON_FUNC0);
Chip_IOCON_PinMux(LPC_IOCON, CHIP_IOCON_PIO[acc_panel[id].acc_panel_beep_port][acc_panel[id].acc_panel_beep_pin], IOCON_MODE_INACT, IOCON_FUNC0);
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].acc_panel_beep_port, acc_panel[id].acc_panel_beep_pin, LOG_HIGH);
//RELAY
Chip_GPIO_SetPinDIROutput(LPC_GPIO, acc_panel[id].relay_port, acc_panel[id].relay_pin);
Chip_IOCON_PinMux(LPC_IOCON, CHIP_IOCON_PIO[acc_panel[id].relay_port][acc_panel[id].relay_pin], IOCON_MODE_PULLUP, IOCON_FUNC0);
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].relay_port, acc_panel[id].relay_pin, LOG_HIGH);
......@@ -47,12 +53,6 @@ void panel_init(uint8_t id)
void panel_deinit(uint8_t id)
{
if (acc_panel[id].card_stream != NULL)
{
vStreamBufferDelete(acc_panel[id].card_stream);
acc_panel[id].card_stream = NULL;
}
if (xTimerDelete(acc_panel[id].timer, 0) != pdFAIL)
{
acc_panel[id].timer = NULL;
......@@ -61,11 +61,34 @@ void panel_deinit(uint8_t id)
weigand_disable(acc_panel[id].acc_panel_port, acc_panel[id].acc_panel_d0_pin, acc_panel[id].acc_panel_d1_pin);
}
void panel_unlock(uint8_t id)
int8_t panel_get_request_from_buffer(uint32_t * user_id)
{
weigand26_buff_item_t item;
size_t bytes_got;
// Suspend if empty
bytes_got = xStreamBufferReceive(_reader_buffer, &item, WEIGAND26_BUFF_ITEM_SIZE, pdMS_TO_TICKS(portMAX_DELAY));
if (bytes_got == WEIGAND26_BUFF_ITEM_SIZE && weigand_is_parity_ok(item.frame))
{
*user_id = (item.frame.facility_code << 16) | item.frame.card_number;
return item.source;
}
return -1;
}
void panel_unlock(uint8_t id, bool with_beep, bool with_ok_led)
{
// Unlock state
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].acc_panel_beep_port, acc_panel[id].acc_panel_beep_pin, LOG_LOW);
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].acc_panel_gled_port, acc_panel[id].acc_panel_gled_pin, LOG_LOW);
if (with_beep)
{
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].acc_panel_beep_port, acc_panel[id].acc_panel_beep_pin, LOG_LOW);
}
if (with_ok_led)
{
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].acc_panel_gled_port, acc_panel[id].acc_panel_gled_pin, LOG_LOW);
}
Chip_GPIO_SetPinState(LPC_GPIO, acc_panel[id].relay_port, acc_panel[id].relay_pin, LOG_LOW);
//Start timer
xTimerStart(acc_panel[id].timer, 0);
......
/*
* This access panel implementation uses Weigand26 card reader protocol.
*/
#ifndef BSP_PANEL_H_
#define BSP_PANEL_H_
......@@ -26,7 +30,6 @@ typedef struct
uint8_t relay_port : 4;
uint8_t relay_pin : 4;
uint16_t open_time_sec;
StreamBufferHandle_t card_stream;
TimerHandle_t timer;
} panel_conf_t; //TOTAL SIZE 6B
#pragma pack(pop)
......@@ -37,7 +40,9 @@ void panel_init(uint8_t id);
void panel_deinit(uint8_t id);
void panel_unlock(uint8_t id);
int8_t panel_get_request_from_buffer(uint32_t * user_id);
void panel_unlock(uint8_t id, bool with_beep, bool with_ok_led);
#endif /* BSP_PANEL_H_ */
......@@ -28,7 +28,6 @@ panel_conf_t acc_panel[DOOR_ACC_PANEL_MAX_COUNT] =
.relay_port = DOOR_0_RELAY_PORT,
.relay_pin = DOOR_0_RELAY_PIN,
.open_time_sec = DOOR_0_OPEN_TIME_MS,
.card_stream = NULL,
.timer = NULL,
},
{
......@@ -43,7 +42,6 @@ panel_conf_t acc_panel[DOOR_ACC_PANEL_MAX_COUNT] =
.relay_port = DOOR_1_RELAY_PORT,
.relay_pin = DOOR_1_RELAY_PIN,
.open_time_sec = DOOR_1_OPEN_TIME_MS,
.card_stream = NULL,
.timer = NULL,
},
{
......@@ -58,31 +56,41 @@ panel_conf_t acc_panel[DOOR_ACC_PANEL_MAX_COUNT] =
.relay_port = DOOR_2_RELAY_PORT,
.relay_pin = DOOR_2_RELAY_PIN,
.open_time_sec = DOOR_2_OPEN_TIME_MS,
.card_stream = NULL,
.timer = NULL,
}
};
static void terminal_user_authorized(uint8_t panel_id)
{
panel_unlock(panel_id);
// TODO
panel_unlock(panel_id, BEEP_ON_SUCCESS, OK_LED_ON_SUCCESS);
}
static void terminal_user_not_authorized(uint8_t panel_id)
{
//TODO
(void)panel_id;
}
static void terminal_process_card(uint8_t facility_code, uint16_t user_number, uint8_t panel_id)
static bool terminal_is_user_auhorized(uint32_t user_id)
{
#ifdef DEVEL_BOARD
//printf("Facility: %u Card: %u Parity: %u\n", facility_code, user_number);
Board_LED_Set(1, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
Board_LED_Set(1, false);
if (facility_code == 12 && user_number == 27762) terminal_user_authorized(panel_id);
#endif
#ifdef DEVEL_BOARD
if (user_id == 7632370) return true;
#endif
return false;
}
static void terminal_user_identified(uint32_t user_id, uint8_t panel_id)
{
if (terminal_is_user_auhorized(user_id))
{
terminal_user_authorized(panel_id);
}
else
{
terminal_user_not_authorized(panel_id);
}
}
static void terminal_task(void *pvParameters)
......@@ -91,32 +99,11 @@ static void terminal_task(void *pvParameters)
while (true)
{
weigand26_frame_t card_data;
size_t bytes_got;
if (acc_panel[ACC_PANEL_0].acc_panel_on)
{
bytes_got = xStreamBufferReceive(acc_panel[ACC_PANEL_0].card_stream, &card_data, sizeof card_data, pdMS_TO_TICKS(0));
if (bytes_got == sizeof card_data && weigand_is_parity_ok(card_data))
{
terminal_process_card(card_data.facility_code, card_data.card_number, ACC_PANEL_0);
}
}
if (acc_panel[ACC_PANEL_1].acc_panel_on)
uint32_t user_id;
uint8_t panel_id = panel_get_request_from_buffer(&user_id);
if (panel_id > 0)
{
bytes_got = xStreamBufferReceive(acc_panel[ACC_PANEL_1].card_stream, &card_data, sizeof card_data, pdMS_TO_TICKS(0));
if (bytes_got == sizeof card_data && weigand_is_parity_ok(card_data))
{
terminal_process_card(card_data.facility_code, card_data.card_number, ACC_PANEL_1);
}
}
if (acc_panel[ACC_PANEL_2].acc_panel_on)
{
bytes_got = xStreamBufferReceive(acc_panel[ACC_PANEL_2].card_stream, &card_data, sizeof card_data, pdMS_TO_TICKS(0));
if (bytes_got == sizeof card_data && weigand_is_parity_ok(card_data))
{
terminal_process_card(card_data.facility_code, card_data.card_number, ACC_PANEL_2);
}
terminal_user_identified(user_id, panel_id);
}
}
}
......@@ -139,17 +126,23 @@ void terminal_reconfigure(panel_conf_t * panel_cfg, uint8_t panel_id)
if (panel_cfg != NULL)
{
memcpy(&acc_panel[panel_id], panel_cfg, sizeof(acc_panel[panel_id]));
memcpy(&acc_panel[panel_id], panel_cfg, sizeof(panel_conf_t));
//disable interface
panel_deinit(panel_id);
//reconfigure interface to card reader
if (acc_panel[panel_id].acc_panel_on)
{
panel_init(panel_id);
}
else
{
//disable interface
panel_deinit(panel_id);
}
}
portEXIT_CRITICAL();
//reconfigure interface to card reader
if (acc_panel[panel_id].acc_panel_on)
else
{
panel_init(panel_id);
}
portEXIT_CRITICAL();
}
......@@ -16,8 +16,10 @@
#define WEIGAND26_FRAME_SIZE 26
typedef union{
struct{
typedef union
{
struct
{
uint32_t odd_parity: 1;
uint32_t card_number : 16;
uint32_t facility_code : 8;
......@@ -25,28 +27,21 @@ typedef union{
uint32_t : 6; //padding
};
uint32_t value;
}weigand26_frame_t;
} weigand26_frame_t;
#define CONSUMER_BUFF_SIZE sizeof(weigand26_frame_t)
// Buffer item type required from consumer of this driver to be used
typedef struct
{
uint8_t source;
weigand26_frame_t frame;
} weigand26_buff_item_t;
typedef struct {
weigand26_frame_t frame_buffer;
uint8_t frame_buffer_ptr;
uint8_t port;
uint8_t pin_d0;
uint8_t pin_d1;
StreamBufferHandle_t consumer_buffer;
}weigand26_t;
#define WEIGAND26_BUFF_ITEM_SIZE sizeof(weigand26_buff_item_t)
void weigand_init(StreamBufferHandle_t buffer, uint8_t dx_port, uint8_t d0_pin, uint8_t d1_pin);
void weigand_init(StreamBufferHandle_t buffer, uint8_t id, uint8_t dx_port, uint8_t d0_pin, uint8_t d1_pin);
void weigand_disable(uint8_t dx_port, uint8_t d0_pin, uint8_t d1_pin);
bool weigand_pending_frame(weigand26_t * instance);
weigand26_frame_t weigand_get_frame(weigand26_t * instance);
uint32_t weigand_get_facility(weigand26_frame_t frame);
uint32_t weigand_get_card(weigand26_frame_t frame);
......
......@@ -15,13 +15,23 @@
#include <limits.h>
#include <assert.h>
typedef struct
{
weigand26_frame_t frame_buffer;
uint8_t frame_buffer_ptr;
uint8_t port;
uint8_t pin_d0;
uint8_t pin_d1;
uint8_t id;
StreamBufferHandle_t consumer_buffer;
} weigand26_t;
static weigand26_t device[WEIGAND_DEVICE_LIMIT];
void weigand_init(StreamBufferHandle_t buffer, uint8_t dx_port, uint8_t d0_pin, uint8_t d1_pin)
void weigand_init(StreamBufferHandle_t buffer, uint8_t id, uint8_t dx_port, uint8_t d0_pin, uint8_t d1_pin)
{
if (dx_port > 3) return;
configASSERT(dx_port < WEIGAND_DEVICE_LIMIT);
//Save device information
device[dx_port].port = dx_port;
......@@ -29,6 +39,7 @@ void weigand_init(StreamBufferHandle_t buffer, uint8_t dx_port, uint8_t d0_pin,
device[dx_port].pin_d1 = d1_pin;
device[dx_port].frame_buffer.value = 0;
device[dx_port].frame_buffer_ptr = WEIGAND26_FRAME_SIZE;
device[dx_port].id = id;
//Enable pull-ups
Chip_IOCON_PinMux(LPC_IOCON, CHIP_IOCON_PIO[dx_port][d0_pin], IOCON_MODE_PULLUP, IOCON_FUNC0);
......@@ -93,7 +104,7 @@ void weigand_int_handler(weigand26_t * device)
Chip_GPIO_ClearInts(LPC_GPIO, device->port, (1 << device->pin_d0));
//Resolve bit value
if (int_states & (1 << device->pin_d1))
if (int_states & (1 << device->pin_d1)) // 0's
{
if (Chip_GPIO_ReadPortBit(LPC_GPIO, device->port, device->pin_d1) == 0)
{
......@@ -101,7 +112,7 @@ void weigand_int_handler(weigand26_t * device)
device->frame_buffer.value |= (1 << device->frame_buffer_ptr);
}
}
else if (int_states & (1 << device->pin_d0))
else if (int_states & (1 << device->pin_d0)) // 1's
{
if (Chip_GPIO_ReadPortBit(LPC_GPIO, device->port, device->pin_d0) == 0)
{
......@@ -109,33 +120,43 @@ void weigand_int_handler(weigand26_t * device)
device->frame_buffer.value &= ~(1 << device->frame_buffer_ptr);
}
}
else
else // Clear other int on same port (FIXME)
{
Chip_GPIO_ClearInts(LPC_GPIO, device->port, 0xFFFFFFFF);
}
//Whole frame received
if (device->frame_buffer_ptr == 0)
if (device->frame_buffer_ptr == 0 && device->consumer_buffer != NULL)
{
xStreamBufferReset(device->consumer_buffer);
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
size_t bytes_sent = xStreamBufferSendFromISR(
device->consumer_buffer,
&device->frame_buffer,
sizeof(weigand26_frame_t),
&pxHigherPriorityTaskWoken);
//Stream buffer should be empty because we reset it
assert(bytes_sent == sizeof(weigand26_frame_t));
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
// Check if not full
if (xStreamBufferIsFull(device->consumer_buffer) == pdFALSE)
{
weigand26_buff_item_t item_to_send = {
device->id,
device->frame_buffer
};
// Send data
size_t bytes_sent = xStreamBufferSendFromISR(
device->consumer_buffer,
&item_to_send,
WEIGAND26_BUFF_ITEM_SIZE,
&pxHigherPriorityTaskWoken);
//Stream buffer should have had enough space
assert(bytes_sent == WEIGAND26_BUFF_ITEM_SIZE);
}
// Discard data
device->frame_buffer_ptr = WEIGAND26_FRAME_SIZE;
device->frame_buffer.value = 0;
// Wake potentially waiting task
portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
}
}
//GPIO port 1 handler
//GPIO port 0 handler
void PIOINT0_IRQHandler(void)
{
NVIC_ClearPendingIRQ(EINT1_IRQn);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment