1
0
mirror of https://github.com/binary-kitchen/doorlockd synced 2024-12-22 18:34:25 +01:00

Rewrite of Door class

Removed old epaper display and added stub for qrcode printing.

Signed-off-by: Ralf Ramsauer <ralf@ramses-pyramidenbau.de>
This commit is contained in:
Ralf Ramsauer 2015-09-16 22:59:14 +02:00
parent b4d6a46025
commit 73868b2d4d
18 changed files with 190 additions and 1785 deletions

View File

@ -15,7 +15,7 @@
#define DEFAULT_LDAP_URI "ldaps://ldap1.binary.kitchen/ ldaps://ldap2.binary.kitchen/ ldaps://ldapm.binary.kitchen/" #define DEFAULT_LDAP_URI "ldaps://ldap1.binary.kitchen/ ldaps://ldap2.binary.kitchen/ ldaps://ldapm.binary.kitchen/"
#define DEFAULT_BINDDN "cn=%s,ou=Users,dc=binary-kitchen,dc=de" #define DEFAULT_BINDDN "cn=%s,ou=Users,dc=binary-kitchen,dc=de"
#define DEFAULT_LOG_FILE "/var/log/doorlockd.log" #define DEFAULT_LOG_FILE "/var/log/doorlockd.log"
#define DEFAULT_PID_FILE "/var/run/doorlockd.pid" #define DEFAULT_SERIAL_DEVICE "/dev/ttyUSB0"
#define TEMPLATE_LOCATION "@CMAKE_INSTALL_PREFIX@/share/doorlockd/template.png" #define TEMPLATE_LOCATION "@CMAKE_INSTALL_PREFIX@/share/doorlockd/template.png"

View File

@ -11,12 +11,10 @@
using namespace std; using namespace std;
void daemonize(const bool daemonize, void daemonize(const string &dir,
const string &dir,
const string &stdinfile, const string &stdinfile,
const string &stdoutfile, const string &stdoutfile,
const string &stderrfile, const string &stderrfile)
const string &pidFile)
{ {
umask(0); umask(0);
@ -26,24 +24,6 @@ void daemonize(const bool daemonize,
throw runtime_error(strerror(errno)); throw runtime_error(strerror(errno));
} }
if (daemonize == true)
{
pid_t pid;
if ((pid = fork()) < 0)
{
throw runtime_error(strerror(errno));
} else if (pid != 0) {
exit(0);
}
pid = setsid();
ofstream pidStream;
pidStream.exceptions(ofstream::failbit | ofstream::badbit);
pidStream.open(pidFile, ofstream::trunc);
pidStream << pid << endl;
}
if (!dir.empty() && chdir(dir.c_str()) < 0) if (!dir.empty() && chdir(dir.c_str()) < 0)
{ {
throw runtime_error(strerror(errno)); throw runtime_error(strerror(errno));

View File

@ -8,11 +8,9 @@
// //
// This function will also redirect stdin, out and err to the // This function will also redirect stdin, out and err to the
// specified files // specified files
void daemonize(const bool daemonize, void daemonize(const std::string &dir,
const std::string &dir,
const std::string &stdinfile, const std::string &stdinfile,
const std::string &stdoutfile, const std::string &stdoutfile,
const std::string &stderrfile, const std::string &stderrfile);
const std::string &pidFile);
#endif #endif

View File

@ -1,35 +1,89 @@
#include <iostream>
#include <wiringPi.h>
#include <unistd.h>
#include "config.h"
#include "logger.h"
#include "door.h" #include "door.h"
using namespace std; Door::Door(const std::string &serDev,
unsigned int baudrate) :
Door::Door() : _baudrate(baudrate),
_l(Logger::get()) _port(_ioService, serDev),
_logger(Logger::get())
{ {
_l(LogLevel::info, "Initializing Raspberry Pi GPIOs"); // Configure serial port
wiringPiSetup(); _port.set_option(boost::asio::serial_port_base::baud_rate(baudrate));
pinMode(_HEARTBEATPIN, OUTPUT); _port.set_option(boost::asio::serial_port_base::character_size(8));
pinMode(_SCHNAPPERPIN, OUTPUT); _port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
pinMode(_LOCKPIN, INPUT); _port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
pullUpDnControl(_LOCKPIN, PUD_UP); _port.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
lock();
_asyncRead();
_ioThread = std::thread([this] () {
_ioService.run();
});
// TODO Ping device
} }
Door::~Door() Door::~Door()
{ {
lock(); lock();
_ioService.stop();
_ioService.reset();
_port.cancel();
_port.close();
_ioThread.join();
} }
Door &Door::get() bool Door::readByte(char &byte, std::chrono::milliseconds timeout)
{ {
static Door d; std::unique_lock<std::mutex> lock(_receiveLock);
return d; _receivedCondition.wait_for(lock, timeout);
if (_byteReady) {
byte = recvBuf;
_byteReady = false;
return true;
}
return false;
}
void Door::_asyncRead()
{
_port.async_read_some(
boost::asio::buffer(&recvBuf, sizeof(recvBuf)),
[this] (const boost::system::error_code &ec, size_t bytes_transferred) {
if (ec) {
// Operation canceled occurs on system shutdown
// So we return without invoking an additional asyncRead()
if (ec == boost::system::errc::operation_canceled)
return;
_logger(LogLevel::error, "Serialport error: %s", ec.message().c_str());
goto out;
}
if (bytes_transferred != 1) {
_logger(LogLevel::error, "Fatal serial error");
goto out;
}
if (recvBuf == 'U') {
_logger(LogLevel::notice, "Someone pushed the unlock button");
}
if (recvBuf == 'L') {
_logger(LogLevel::notice, "Someone pushed the lock button");
_logger(LogLevel::notice, "Locking...");
lock();
goto out;
}
// TODO EMERGENCY DOOR BUTTON
_byteReady = true;
_receivedCondition.notify_one();
out:
_asyncRead();
});
} }
Door::State Door::state() const Door::State Door::state() const
@ -39,97 +93,66 @@ Door::State Door::state() const
void Door::lock() void Door::lock()
{ {
std::lock_guard<std::mutex> l(_mutex); _stateMutex.lock();
_l(LogLevel::notice, "Executing Pre Lock Script"); if (_state == State::Locked) {
system(PRE_LOCK_SCRIPT); _stateMutex.unlock();
return;
digitalWrite(_SCHNAPPERPIN, HIGH);
_l(LogLevel::info, "Door closed");
if (_state == State::Unlocked)
{
// Stop the Heartbeat Thread
_state = State::Locked;
_heartbeat.join();
} }
_l(LogLevel::notice, "Executing Post Lock Script"); _state = State::Locked;
system(POST_LOCK_SCRIPT); _stateMutex.unlock();
_heartbeatCondition.notify_one();
_heartbeatThread.join();
} }
void Door::unlock() void Door::unlock()
{ {
_l(LogLevel::notice, "Executing Pre Unlock Script"); _stateMutex.lock();
system(PRE_UNLOCK_SCRIPT);
// In any case, klacker the schnapper
_schnapper = true; _schnapper = true;
// If heartbeat is already running, return if(_state == State::Unlocked) {
if (_state == State::Unlocked) _stateMutex.unlock();
{
return; return;
} }
// If not, first set state to unlocked
_state = State::Unlocked; _state = State::Unlocked;
_stateMutex.unlock();
// Start the Heartbeat Thread _heartbeatThread = std::thread([this] () {
_heartbeat = std::thread([this] () { std::unique_lock<std::mutex> lock(_heartbeatMutex);
// One "beat" is one complete cycle of the heartbeat clock
auto beat = [this] () {
digitalWrite(_HEARTBEATPIN, HIGH);
usleep(10000);
digitalWrite(_HEARTBEATPIN, LOW);
usleep(10000);
};
// The default of the Schnapperpin: always high
digitalWrite(_SCHNAPPERPIN, HIGH);
// Heartbeat while the state is unlocked
while (_state == State::Unlocked) { while (_state == State::Unlocked) {
if (_state == State::Unlocked) {
writeCMD('u');
// In case of schnapper, send 0x55 resp. 0xaa to the schnapperpin if (_schnapper) {
if (_schnapper == true)
{
for (int i = 0; i < 32 ; i++)
{
// Set '0'
digitalWrite(_SCHNAPPERPIN, LOW);
// cycle and send
beat();
// Set '1'
digitalWrite(_SCHNAPPERPIN, HIGH);
// cycle and send
beat();
}
// Reset schnapperpin
digitalWrite(_SCHNAPPERPIN, HIGH);
// and deactivate schnapper for the next round
_schnapper = false; _schnapper = false;
} writeCMD('s');
// Heartbeat
beat();
if (!digitalRead(_LOCKPIN)) {
std::thread([this] () {
_l(LogLevel::info, "Incoming door close request on button press");
lock();
}).detach();
// Busy wait till door is locked
while(_state == State::Unlocked);
} }
} }
_heartbeatCondition.wait_for(lock, Milliseconds(400));
}
writeCMD('l');
}); });
_l(LogLevel::info, "Door opened");
_l(LogLevel::notice, "Executing Post Unlock Script");
system(POST_UNLOCK_SCRIPT);
} }
bool Door::writeCMD(char c)
{
std::lock_guard<std::mutex> l(_serialMutex);
_port.write_some(boost::asio::buffer(&c, sizeof(c)));
char response;
if (readByte(response, Milliseconds(100)))
{
if (c != response) {
_logger(LogLevel::error, "Sent command '%c' but gor response '%c'", c, response);
return false;
}
return true;
}
_logger(LogLevel::error, "Sent Serial command, but got no response!");
return false;
}

View File

@ -2,64 +2,69 @@
#define DOOR_H #define DOOR_H
#include <string> #include <string>
#include <functional>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <condition_variable>
#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include "logger.h" #include "logger.h"
/* class Door final
* The Door class. {
*
* This class exists as a singleton as only one door and hence one object may exist.
* Available via the get() method.
*
* This class is responsible for opening and closing the door by sending
* the heartbeat to the AVR board via Raspberry Pi GPIOs
*
* Whenever the unlock() is called, this class also sends a 0x55 resp. 0xaa
* to the AVR in order to klacker the schnapper.
*/
class Door {
public: public:
// Returns the singleton Door(const std::string &serDev,
static Door &get(); unsigned int baudrate = 9600);
~Door(); ~Door();
enum class State {Locked, Unlocked}; enum class State {Unlocked, Locked};
// Current state of the door
State state() const; State state() const;
// Lock the door
void lock(); void lock();
// Unlock the door
void unlock(); void unlock();
private: private:
Door(); using Milliseconds = std::chrono::milliseconds;
// used for logging const unsigned int _baudrate;
const Logger &_l;
// Indicates the internal state: Door is open or locked // To prevent concurrent writes
volatile State _state = { Door::State::Locked }; std::mutex _serialMutex = { };
// A Heartbeat thread is started when the door is unlocked boost::asio::io_service _ioService = { };
std::thread _heartbeat = { }; boost::asio::serial_port _port;
// Read by the Heartbeat thread if it should klacker the schnapper or not std::mutex _stateMutex = { };
bool _schnapper = { false }; volatile State _state = { State::Locked };
// Mutex to avoid concurrent locks std::thread _heartbeatThread = { };
std::mutex _mutex = { }; std::mutex _heartbeatMutex = { };
std::condition_variable _heartbeatCondition = { };
// WiringPi GPIO Pins std::thread _ioThread = { };
static constexpr int _HEARTBEATPIN = 10; void _asyncRead();
static constexpr int _SCHNAPPERPIN = 7;
static constexpr int _LOCKPIN = 15; volatile bool _schnapper = { false };
// Indicates if recvBuf contains a valid response from AVR Board
volatile bool _byteReady = { false };
// Actual response
char recvBuf = { };
std::condition_variable _receivedCondition = { };
std::mutex _receiveLock = { };
const Logger &_logger;
// Writed command to AVR board
bool writeCMD(char c);
// Receives one byte and returns true or returns false on timeout
bool readByte(char &byte, Milliseconds timeout);
}; };
#endif #endif

View File

@ -1,55 +0,0 @@
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include "logger.h"
extern "C" {
#include "epaper/bsp.h"
#include "epaper/Display_Controller.h"
}
#include "epaper.h"
#include "config.h"
using namespace std;
Epaper::Epaper() :
_logger(Logger::get())
{
memset(_prevImg, 0xFF, _ARRAY_SIZE);
// Initialize Epaper library
bsp_init();
}
Epaper::~Epaper()
{
}
Epaper &Epaper::get()
{
static Epaper e;
return e;
}
void Epaper::draw(const string &uri)
{
unsigned char buffer[_ARRAY_SIZE];
snprintf((char*)buffer, _ARRAY_SIZE,
"qrencode -l M -d 100 -s 5 \"%s\" -t png -o -"
"| composite -geometry +90+0 /dev/stdin " TEMPLATE_LOCATION " -colorspace gray -depth 1 gray:-",
uri.c_str());
FILE* f = popen((const char*)buffer, "r");
int i = fread(buffer, _ARRAY_SIZE, 1, f);
if (i != 1)
{
_logger(LogLevel::error, "Image format error");
pclose(f);
return;
}
pclose(f);
epd_DisplayImg(EPDType_270, buffer, _prevImg);
memcpy(_prevImg, buffer, _ARRAY_SIZE);
}

View File

@ -1,42 +0,0 @@
#ifndef EPAPER_H
#define EPAPER_H
#include <string>
#include <array>
#include "logger.h"
/*
* The "Epaper" class.
*
* Wrapper for the epaper third Party library.
*
* Exists as singleton, as only one display may exist.
*/
class Epaper {
public:
static Epaper &get();
~Epaper();
// This function will draw template.png to the display and
// convert the uri to a QR-Code and paste it on top of template.png
// using imagemagick
void draw(const std::string &uri);
private:
constexpr static int _HEIGHT = 176; // In Pixel
constexpr static int _WIDTH = 33; // In Byte
constexpr static int _ARRAY_SIZE = _HEIGHT * _WIDTH;
Epaper();
// The old image is needed when updating the Epaper display
// It informs the display which pixels have to be flipped
uint8_t _prevImg[_ARRAY_SIZE];
const Logger &_logger;
};
#endif

View File

@ -1,650 +0,0 @@
// Copyright 2013 Pervasive Displays, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.
/******************************************************************************
* Includes
*****************************************************************************/
//#include "driver_config.h"
//#include "target_config.h"
//#include "type.h"
//#include "gpio.h"
#include "Display_COG_Process.h"
#include "Display_Hardware_Driver.h"
#include "Display_Controller.h"
/******************************************************************************
* Defines and typedefs
*****************************************************************************/
#define _GaugeFrameTimeMark 0
const COG_Parameters_t COG_Parameters[3]= {
{ //for 1.44"
{0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0x00},
0x03,
(128/8),
96,
(((128+96)*2)/8),
(43),
480
},
{ //for 2.0"
{0x00,0x00,0x00,0x00,0x01,0xFF,0xE0,0x00},
0x03,
(200/8),
96,
(((200+96)*2)/8)+1,
(53),
480
},
{ //for 2.7"
{0x00,0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00},
0x00,
(264/8),
176,
(((264+176)*2)/8)+1,
105,
630
},
};
const uint8_t ScanTable[4] = {0xC0, 0x30, 0x0C, 0x03};
/******************************************************************************
* Local variables
*****************************************************************************/
static uint32_t StageTime = 480;
static COG_LineDataPacket_t COG_Line;
static uint16_t EPD_Type_Index = 0;
static uint16_t cnt = 0;
static uint32_t Currentframe;
static uint8_t *DataLineEven;
static uint8_t *DataLineOdd;
static uint8_t *DataLineScan;
static uint8_t *DisplayOrgPtr;
/******************************************************************************
* Local functions
*****************************************************************************/
static void SetTemperature_Factor(uint8_t EPD_Type_Index)
{
int16_t Temperature;
//Get current temperature
Temperature = epd_get_temperature();
if (Temperature < -10)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 17;
}
else if (Temperature < -5)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 12;
}
else if (Temperature < 5)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 8;
}
else if (Temperature < 10)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 4;
}
else if (Temperature < 15)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 3;
}
else if (Temperature < 20)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 2;
}
else if (Temperature < 40)
{
StageTime = COG_Parameters[EPD_Type_Index].StageTime * 1;
}
else
{
StageTime = (COG_Parameters[EPD_Type_Index].StageTime * 7)/10;
}
}
static void Driver_TypeSelect(uint8_t typeIndex)
{
switch(typeIndex)
{
case EPDType_144:
DataLineEven=&COG_Line.LineDatas.COG_144LineData.Even[0];
DataLineOdd=&COG_Line.LineDatas.COG_144LineData.Odd[0];
DataLineScan=&COG_Line.LineDatas.COG_144LineData.Scan[0];
break;
case EPDType_200:
DataLineEven=&COG_Line.LineDatas.COG_20LineData.Even[0];
DataLineOdd=&COG_Line.LineDatas.COG_20LineData.Odd[0];
DataLineScan=&COG_Line.LineDatas.COG_20LineData.Scan[0];
break;
case EPDType_270:
DataLineEven=&COG_Line.LineDatas.COG_27LineData.Even[0];
DataLineOdd=&COG_Line.LineDatas.COG_27LineData.Odd[0];
DataLineScan=&COG_Line.LineDatas.COG_27LineData.Scan[0];
break;
}
}
//#pragma GCC optimize ("-O3")
static void Display_Stage_1 (uint8_t *PreviousPicture)
{
uint16_t i,j,k; // general counters
uint8_t TempByte; // Temporary storage for image data check
uint16_t StartClock;
#ifdef DISPLAY_180_DEGREE
uint8_t *DataLinePrt;
DisplayOrgPtr = (PreviousPicture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL));
#else
DisplayOrgPtr = PreviousPicture;
#endif
Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime;
//TestPinTrigger();
cnt = 0;
StartClock = epd_GetCurrentTimeTick();
do
{
// TestPin2Trigger();
PreviousPicture = DisplayOrgPtr;
#ifdef DISPLAY_180_DEGREE
DataLinePrt = PreviousPicture;
#endif
for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line
{
// SPI (0x04, ...)
epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel);
k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1;
for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // check every bit in the line
{
TempByte = (*PreviousPicture++);
#ifdef DISPLAY_180_DEGREE
DataLineEven[j] = ((TempByte & 0x80) ? BLACK3 : WHITE3)
| ((TempByte & 0x20) ? BLACK2 : WHITE2)
| ((TempByte & 0x08) ? BLACK1 : WHITE1)
| ((TempByte & 0x02) ? BLACK0 : WHITE0);
DataLineOdd[k--] = ((TempByte & 0x01) ? BLACK3 : WHITE3)
| ((TempByte & 0x04) ? BLACK2 : WHITE2)
| ((TempByte & 0x10) ? BLACK1 : WHITE1)
| ((TempByte & 0x40) ? BLACK0 : WHITE0);
DataLinePrt--;
#else
DataLineOdd[j] = ((TempByte & 0x80) ? BLACK3 : WHITE3)
| ((TempByte & 0x20) ? BLACK2 : WHITE2)
| ((TempByte & 0x08) ? BLACK1 : WHITE1)
| ((TempByte & 0x02) ? BLACK0 : WHITE0);
DataLineEven[k--] = ((TempByte & 0x01) ? BLACK3 : WHITE3)
| ((TempByte & 0x04) ? BLACK2 : WHITE2)
| ((TempByte & 0x10) ? BLACK1 : WHITE1)
| ((TempByte & 0x40) ? BLACK0 : WHITE0);
#endif
}
#ifdef DISPLAY_180_DEGREE
PreviousPicture = DataLinePrt;
#endif
DataLineScan[(i>>2)] = ScanTable[(i%4)];
// SPI (0x0a, line data....)
epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize);
// SPI (0x02, 0x25)
epd_SPI_Send_Byte(0x02, 0x2F);
DataLineScan[(i>>2)] = 0;
}
#if(!_GaugeFrameTimeMark)
if(COG_Parameters[EPD_Type_Index].FrameTime>0)
{
while(Currentframe>(epd_GetCurrentTimeTick() - StartClock));
}
#endif
//TestPin2Trigger();
Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ;
cnt++;
}while (StageTime>Currentframe);
// TestPin2Trigger();
while(StageTime>(epd_GetCurrentTimeTick() - StartClock));
// TestPin2Trigger();
// TestPinTrigger();
}
//#pragma GCC optimize ("-O3")
static void Display_Stage_2 (uint8_t *PreviousPicture)
{
uint16_t i, j, k; // general counters
uint8_t TempByte; // Temporary storage for image data check
uint16_t StartClock;
#ifdef DISPLAY_180_DEGREE
uint8_t *DataLinePrt;
DisplayOrgPtr = (PreviousPicture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL));
#else
DisplayOrgPtr = PreviousPicture;
#endif
// TestPinTrigger();
cnt = 0;
Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime;
StartClock = epd_GetCurrentTimeTick();
do
{
// TestPin2Trigger();
PreviousPicture = DisplayOrgPtr;
#ifdef DISPLAY_180_DEGREE
DataLinePrt = PreviousPicture;
#endif
for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line
{
// SPI (0x04, ...)
epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel);
k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1;
for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // make every bit in the line black
{
TempByte =(*PreviousPicture++);
#ifdef DISPLAY_180_DEGREE
DataLineEven[j] = ((TempByte & 0x80) ? WHITE3 : NOTHING)
| ((TempByte & 0x20) ? WHITE2 : NOTHING)
| ((TempByte & 0x08) ? WHITE1 : NOTHING)
| ((TempByte & 0x02) ? WHITE0 : NOTHING);
DataLineOdd[k--] = ((TempByte & 0x01) ? WHITE3 : NOTHING)
| ((TempByte & 0x04) ? WHITE2 : NOTHING)
| ((TempByte & 0x10) ? WHITE1 : NOTHING)
| ((TempByte & 0x40) ? WHITE0 : NOTHING);
DataLinePrt--;
#else
DataLineOdd[j] = ((TempByte & 0x80) ? WHITE3 : NOTHING)
| ((TempByte & 0x20) ? WHITE2 : NOTHING)
| ((TempByte & 0x08) ? WHITE1 : NOTHING)
| ((TempByte & 0x02) ? WHITE0 : NOTHING);
DataLineEven[k--] = ((TempByte & 0x01) ? WHITE3 : NOTHING)
| ((TempByte & 0x04) ? WHITE2 : NOTHING)
| ((TempByte & 0x10) ? WHITE1 : NOTHING)
| ((TempByte & 0x40) ? WHITE0 : NOTHING);
#endif
}
#ifdef DISPLAY_180_DEGREE
PreviousPicture = DataLinePrt;
#endif
DataLineScan[(i>>2)] = ScanTable[(i%4)];
// SPI (0x0a, line data....)
epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize);
epd_SPI_Send_Byte(0x02, 0x25);
DataLineScan[(i>>2)] = 0;
}
#if(!_GaugeFrameTimeMark)
if(COG_Parameters[EPD_Type_Index].FrameTime>0)
{
while(Currentframe>(epd_GetCurrentTimeTick() - StartClock));
}
#endif
//TestPin2Trigger();
Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ;
cnt++;
}while (StageTime>Currentframe);
// TestPin2Trigger();
while(StageTime>(epd_GetCurrentTimeTick() - StartClock));
// TestPin2Trigger();
// TestPinTrigger();
}
//#pragma GCC optimize ("-O3")
static void Display_Stage_3 (uint8_t *Picture)
{
uint16_t i, j,k; // general counters
uint8_t TempByte; // Temporary storage for image data check
uint16_t StartClock;
#ifdef DISPLAY_180_DEGREE
uint8_t *DataLinePrt;
DisplayOrgPtr = (Picture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL));
#else
DisplayOrgPtr = Picture;
#endif
Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime;
cnt = 0;
// TestPinTrigger();
StartClock = epd_GetCurrentTimeTick();
do
{
// TestPin2Trigger();
Picture = DisplayOrgPtr;
#ifdef DISPLAY_180_DEGREE
DataLinePrt = Picture;
#endif
for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line
{
// SPI (0x04, 0x03)
epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel);
k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1;
for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // check every bit in the line
{
TempByte = (*Picture++);
#ifdef DISPLAY_180_DEGREE
DataLineEven[j] = ((TempByte & 0x80) ? BLACK3 : NOTHING)
| ((TempByte & 0x20) ? BLACK2 : NOTHING )
| ((TempByte & 0x08) ? BLACK1 : NOTHING )
| ((TempByte & 0x02) ? BLACK0 : NOTHING );
DataLineOdd[k--] = ((TempByte & 0x01) ? BLACK3 : NOTHING)
| ((TempByte & 0x04) ? BLACK2 : NOTHING )
| ((TempByte & 0x10) ? BLACK1 : NOTHING )
| ((TempByte & 0x40) ? BLACK0 : NOTHING );
DataLinePrt--;
#else
DataLineOdd[j] = ((TempByte & 0x80) ? BLACK3 : NOTHING)
| ((TempByte & 0x20) ? BLACK2 : NOTHING )
| ((TempByte & 0x08) ? BLACK1 : NOTHING )
| ((TempByte & 0x02) ? BLACK0 : NOTHING );
DataLineEven[k--] = ((TempByte & 0x01) ? BLACK3 : NOTHING)
| ((TempByte & 0x04) ? BLACK2 : NOTHING )
| ((TempByte & 0x10) ? BLACK1 : NOTHING )
| ((TempByte & 0x40) ? BLACK0 : NOTHING );
#endif
}
#ifdef DISPLAY_180_DEGREE
Picture = DataLinePrt;
#endif
DataLineScan[(i>>2)] = ScanTable[(i%4)];
// SPI (0x0a, line data....)
epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize);
epd_SPI_Send_Byte(0x02, 0x2F);
DataLineScan[(i>>2)] = 0;
}
#if(!_GaugeFrameTimeMark)
if(COG_Parameters[EPD_Type_Index].FrameTime>0)
{
while(Currentframe>(epd_GetCurrentTimeTick() - StartClock));
}
#endif
//TestPin2Trigger();
Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ;
cnt++;
}while (StageTime>Currentframe);
// TestPin2Trigger();
while(StageTime>(epd_GetCurrentTimeTick() - StartClock));
// TestPin2Trigger();
// TestPinTrigger();
}
//#pragma GCC optimize ("-O3")
static void Display_Stage_4 (uint8_t *Picture)
{
uint16_t i, j,k; // general counters
uint8_t TempByte; // Temporary storage for image data check
uint16_t StartClock;
#ifdef DISPLAY_180_DEGREE
uint8_t *DataLinePrt;
DisplayOrgPtr = (Picture+(uint32_t)((COG_Parameters[EPD_Type_Index].VERTICAL-1)*COG_Parameters[EPD_Type_Index].HORIZONTAL));
#else
DisplayOrgPtr = Picture;
#endif
Currentframe = (uint32_t)COG_Parameters[EPD_Type_Index].FrameTime;
cnt = 0;
// TestPinTrigger();
StartClock = epd_GetCurrentTimeTick();
do
{
// TestPin2Trigger();
Picture = DisplayOrgPtr;
#ifdef DISPLAY_180_DEGREE
DataLinePrt = Picture;
#endif
for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line
{
// SPI (0x04, ...)
epd_SPI_Send_Byte(0x04, COG_Parameters[EPD_Type_Index].VoltageLevel);
k = COG_Parameters[EPD_Type_Index].HORIZONTAL-1;
for (j = 0; j < COG_Parameters[EPD_Type_Index].HORIZONTAL; j++) // check every bit in the line
{
TempByte =(*Picture++);
#ifdef DISPLAY_180_DEGREE
DataLineEven[j] = ((TempByte & 0x80) ? WHITE3 : BLACK3 )
| ((TempByte & 0x20) ? WHITE2 : BLACK2 )
| ((TempByte & 0x08) ? WHITE1 : BLACK1 )
| ((TempByte & 0x02) ? WHITE0 : BLACK0 );
DataLineOdd[k--] = ((TempByte & 0x01) ? WHITE3 : BLACK3 )
| ((TempByte & 0x04) ? WHITE2 : BLACK2 )
| ((TempByte & 0x10) ? WHITE1 : BLACK1 )
| ((TempByte & 0x40) ? WHITE0 : BLACK0 );
DataLinePrt--;
#else
DataLineOdd[j] = ((TempByte & 0x80) ? WHITE3 : BLACK3 )
| ((TempByte & 0x20) ? WHITE2 : BLACK2 )
| ((TempByte & 0x08) ? WHITE1 : BLACK1 )
| ((TempByte & 0x02) ? WHITE0 : BLACK0 );
DataLineEven[k--] = ((TempByte & 0x01) ? WHITE3 : BLACK3 )
| ((TempByte & 0x04) ? WHITE2 : BLACK2 )
| ((TempByte & 0x10) ? WHITE1 : BLACK1 )
| ((TempByte & 0x40) ? WHITE0 : BLACK0 );
#endif
}
#ifdef DISPLAY_180_DEGREE
Picture = DataLinePrt;
#endif
DataLineScan[(i>>2)] = ScanTable[(i%4)];
// SPI (0x0a, line data....)
epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize);
epd_SPI_Send_Byte(0x02, 0x2F);
DataLineScan[(i>>2)] = 0;
}
#if(!_GaugeFrameTimeMark)
if(COG_Parameters[EPD_Type_Index].FrameTime>0)
{
while(Currentframe>(epd_GetCurrentTimeTick() - StartClock));
}
#endif
//TestPin2Trigger();
Currentframe=(uint32_t)(epd_GetCurrentTimeTick() - StartClock)+COG_Parameters[EPD_Type_Index].FrameTime ;
cnt++;
}while (StageTime>Currentframe);
// TestPin2Trigger();
while(StageTime>(epd_GetCurrentTimeTick() - StartClock));
// TestPin2Trigger();
// TestPinTrigger();
}
static void Display_Nothing (void)
{
uint16_t i; // general counters
for (i = 0; i < COG_Parameters[EPD_Type_Index].HORIZONTAL; i++) // make every bit in the line white
{
DataLineEven[i] = 0x00;
DataLineOdd[i] = 0x00;
}
for (i = 0; i < COG_Parameters[EPD_Type_Index].VERTICAL; i++) // for every line
{
epd_SPI_Send_Byte(0x04, 0x03);
DataLineScan[(i>>2)] = ScanTable[(i%4)];
// SPI (0x0a, line data....)
epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize);
epd_SPI_Send_Byte(0x02, 0x2F);
}
}
static void Dummy_line(void)
{
uint16_t i;
for (i = 0; i < COG_Parameters[EPD_Type_Index].DataLineSize; i++)
{
COG_Line.uint8[i] = 0x00;
}
epd_SPI_Send_Byte(0x04, 0x03);
// SPI (0x0a, line data....)
epd_SPI_Send(0x0a, (uint8_t *)&COG_Line.uint8, COG_Parameters[EPD_Type_Index].DataLineSize);
epd_SPI_Send_Byte(0x02, 0x2F);
}
/******************************************************************************
* Public functions
*****************************************************************************/
void epd_HwInit(void)
{
epd_InitDisplayHardware();
}
void epd_PowerOn(void)
{
epd_discharge_low();
epd_rst_low();
epd_cs_low();
epd_spi_init();
epd_pwm_active(5);
epd_panelon_on();
epd_pwm_active(10);
epd_cs_high();
//epd_border_high();
epd_rst_high();
epd_pwm_active(5);
epd_rst_low();
epd_pwm_active(5);
epd_rst_high();
epd_pwm_active(5);
}
void epd_InitializeDriver(uint8_t EPDIndex)
{
uint8_t SendBuffer[2];
uint16_t k;
EPD_Type_Index = EPDIndex;
//Data Line Clear
for (k = 0; k <= __LineDataSize; k ++)
{
COG_Line.uint8[k] = 0x00;
}
Driver_TypeSelect(EPDIndex);
k = 0;
SetTemperature_Factor(EPDIndex);
/*while (DRIVERBUSY_Get())
{
delayT32B0Us(500);
if((k++)>=1000) return;//wait 500 ms
}
*/
// SPI (0x01, 0x0000, 0x0000, 0x01ff, 0xe000)
epd_SPI_Send(0x01, (uint8_t *)&COG_Parameters[EPDIndex].ChannelSelect, 8);
epd_SPI_Send_Byte(0x06, 0xff);
epd_SPI_Send_Byte(0x07, 0x9d);
epd_SPI_Send_Byte(0x08, 0x00);
// SPI (0x09, 0xd000)
SendBuffer[0] = 0xd0;
SendBuffer[1] = 0x00;
epd_SPI_Send(0x09, SendBuffer, 2);
epd_SPI_Send_Byte(0x04,COG_Parameters[EPDIndex].VoltageLevel);
epd_SPI_Send_Byte(0x03, 0x01);
epd_SPI_Send_Byte(0x03, 0x00);
epd_pwm_active(5);
epd_SPI_Send_Byte(0x05, 0x01);
epd_pwm_active(30);
epd_SPI_Send_Byte(0x05, 0x03);
epd_delay_ms(30);
epd_SPI_Send_Byte(0x05, 0x0f);
epd_delay_ms(30);
epd_SPI_Send_Byte(0x02, 0x24);
}
void epd_Display (uint8_t *pNewImg, uint8_t *pPrevImg)
{
//COG Process - update display in four steps
Display_Stage_1(pPrevImg);
Display_Stage_2(pPrevImg);
Display_Stage_3(pNewImg);
Display_Stage_4(pNewImg);
}
void epd_PowerOff (void)
{
Display_Nothing();
Dummy_line();
epd_delay_ms(25);
//border_low();
//epd_delay_ms(_30ms);
//border_high();
epd_SPI_Send_Byte(0x03, 0x01);
epd_SPI_Send_Byte(0x02, 0x05);
epd_SPI_Send_Byte(0x05, 0x0E);
epd_SPI_Send_Byte(0x05, 0x02);
epd_SPI_Send_Byte(0x04, 0x0C);
epd_delay_ms(120);
epd_SPI_Send_Byte(0x05, 0x00);
epd_SPI_Send_Byte(0x07, 0x0D);
epd_SPI_Send_Byte(0x04, 0x50);
epd_delay_ms(40);
epd_SPI_Send_Byte(0x04, 0xA0);
epd_delay_ms(40);
epd_SPI_Send_Byte(0x04, 0x00);
epd_rst_low();
epd_cs_low();
epd_spi_detach();
epd_panelon_off();
//epd_border_low();
epd_discharge_high();
epd_delay_ms(150);
epd_discharge_low();
}

View File

@ -1,120 +0,0 @@
// Copyright 2013 Pervasive Displays, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.
#ifndef __Display_COG_Process_H_
#define __Display_COG_Process_H_
/******************************************************************************
* Includes
*****************************************************************************/
#include "bsp.h"
/******************************************************************************
* Defines and typedefs
*****************************************************************************/
#define BLACK0 (0x03)
#define BLACK1 (0x0C)
#define BLACK2 (0x30)
#define BLACK3 (0xc0)
#define WHITE0 (0x02)
#define WHITE1 (0x08)
#define WHITE2 (0x20)
#define WHITE3 (0x80)
#define NOTHING (0x00)
#define SCANON (0xC0)
#define __LineDataSize 111
/*
enum
{
_5ms,
_10ms,
_25ms,
_30ms,
_40ms,
_120ms,
_150ms,
_300ms
};
*/
typedef enum
{
EPDType_144 = 0, //1.44" display
EPDType_200 = 1, //2.0" display
EPDType_270 = 2 //2.7" display
} EPDType_t;
#define EPD_TYPE_144 0
#define EPD_TYPE_200 1
#define EPD_TYPE_270 2
typedef struct
{
uint8_t Even[16];
uint8_t Scan[24];
uint8_t Odd [16];
} COG_144_LineData_t;
typedef struct
{
uint8_t Even[25];
uint8_t Scan[24];
uint8_t Odd [25];
uint8_t DummyData;
} COG_20_LineData_t;
typedef struct
{
uint8_t Even[33];
uint8_t Scan[44];
uint8_t Odd [33];
uint8_t DummyData;
} COG_27_LineData_t;
typedef union
{
union
{
COG_144_LineData_t COG_144LineData;
COG_20_LineData_t COG_20LineData;
COG_27_LineData_t COG_27LineData;
} LineDatas;
uint8_t uint8[__LineDataSize];
} COG_LineDataPacket_t;
typedef struct
{
uint8_t ChannelSelect[8];
uint8_t VoltageLevel;
uint16_t HORIZONTAL;
uint16_t VERTICAL;
uint8_t DataLineSize;
uint16_t FrameTime;
uint16_t StageTime;
} COG_Parameters_t;
extern const COG_Parameters_t COG_Parameters[3];
/******************************************************************************
* Prototypes
*****************************************************************************/
void epd_HwInit(void);
void epd_PowerOn(void);
void epd_InitializeDriver(uint8_t EPDIndex);
void epd_Display(uint8_t *pNewImg, uint8_t *pPrevImg);
void epd_PowerOff(void);
#endif //__Display_COG_Process_H_

View File

@ -1,40 +0,0 @@
// Copyright 2013 Pervasive Displays, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.
/******************************************************************************
* Includes
*****************************************************************************/
//#include "driver_config.h"
//#include "type.h"
//#include "gpio.h"
#include "Display_Controller.h"
/******************************************************************************
* Global Functions
*****************************************************************************/
void epd_DisplayImg(EPDType_t EPDType, uint8_t *pNewImg, uint8_t *pPrevImg)
{
//always initialize display (has been powered off before)
epd_HwInit();
epd_PowerOn();
epd_InitializeDriver(EPDType);
//display new picture, but first remove old one
epd_Display(pNewImg, pPrevImg);
//power down display - picture still displayed
epd_PowerOff();
}

View File

@ -1,34 +0,0 @@
// Copyright 2013 Pervasive Displays, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.
#ifndef __Display_Controller_H_
#define __Display_Controller_H_
/******************************************************************************
* Includes
*****************************************************************************/
#include "bsp.h"
#include "Display_COG_Process.h"
/******************************************************************************
* Defines and typedefs
*****************************************************************************/
#define DISPLAY_IN_USE EPD_TYPE_270
/******************************************************************************
* Prototypes
*****************************************************************************/
void epd_DisplayImg(EPDType_t EPDType, uint8_t *pNewImg, uint8_t *pPrevImg);
#endif //__Display_Controller_H_

View File

@ -1,258 +0,0 @@
// Copyright 2013 Pervasive Displays, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.
/******************************************************************************
* Includes
*****************************************************************************/
#include "Display_Hardware_Driver.h"
/******************************************************************************
* Public functions
*****************************************************************************/
void epd_cs_high(void)
{
// CS_SET_HIGH;
bsp_pinOut(BSP_PIN_6, 1);
}
void epd_cs_low(void)
{
// CS_SET_LOW;
bsp_pinOut(BSP_PIN_6, 0);
}
void epd_rst_high(void)
{
// RST_SET_HIGH;
bsp_pinOut(BSP_PIN_12, 1);
}
void epd_rst_low(void)
{
// RST_SET_LOW;
bsp_pinOut(BSP_PIN_12, 0);
}
void epd_discharge_high(void)
{
// DISCHARGE_SET_HIGH;
bsp_pinOut(BSP_PIN_14, 1);
}
void epd_discharge_low(void)
{
// DISCHARGE_SET_LOW;
bsp_pinOut(BSP_PIN_14, 0);
}
void epd_panelon_off(void)
{
// PANELON_SET_LOW;
bsp_pinOut(BSP_PIN_13, 0);
}
void epd_panelon_on(void)
{
// PANELON_SET_HIGH;
bsp_pinOut(BSP_PIN_13, 1);
}
void epd_border_high(void)
{
// BORDER_SET_HIGH;
}
void epd_border_low(void)
{
// BORDER_SET_LOW;
}
void epd_delay_ms(uint32_t Time)
{
bsp_delayMs(Time);
}
int16_t epd_get_temperature(void)
{
return bsp_getTemp();
}
uint32_t epd_GetCurrentTimeTick(void)
{
return bsp_getMsTicks();
}
//******************************************************************
//PWM Configuration/Control
//******************************************************************
#if 0
volatile uint32_t period = 500; //96Khz PWM frequency
void epd_pwm_disable(void)
{
disable_timer16(1);
LPC_IOCON->PIO1_9 &= 0xFC;//Disable PWM,set general IO
PWM_DIR_OUT();
PWM_SET_LOW();
}
void epd_pwm_active(void)
{
PWM_SET_HIGH();
/* Initialize the PWM in timer32_1 enabling match0 output */
init_timer16PWM(1, period, MATCH0,0);
setMatch_timer16PWM (1, 1, period/8);
enable_timer16(1);
}
#endif
void epd_pwm_active(uint16_t delayInMs)
{
uint16_t numOfIterations;
numOfIterations = delayInMs * 100;
// PWM_DIR_OUT;
bsp_pinMode(BSP_PIN_11, BSP_PINMODE_OUTPUT);
for(; numOfIterations > 0; numOfIterations--)
{
// PWM_SET_HIGH;
bsp_pinOut(BSP_PIN_11, 1);
bsp_delayUs(5); //100kHz (96kHz ideal)
// PWM_SET_LOW;
bsp_pinOut(BSP_PIN_11, 0);
bsp_delayUs(5);
}
}
//******************************************************************
//SPI Configuration
//******************************************************************
void epd_spi_detach(void)
{
#if 0
LPC_IOCON->PIO0_8 &= 0xFC;; /* SSP I/O config */
SPIMISO_DIR_OUT();
SPIMISO_Set(Low);
LPC_IOCON->PIO0_9 &= 0xFC; /* SSP MOSI */
SPIMOSI_DIR_OUT();
SPIMOSI_Set(Low);
LPC_IOCON->PIO2_11 &= 0xFC;
SPICLK_DIR_OUT();
SPICLK_Set(Low);
#endif
}
void epd_spi_init (void)
{
bsp_spiInit();
//SSP_IOConfig( SSP_PORT ); /* initialize SSP port */
//SSP_Init( SSP_PORT );
}
void epd_SPI_Send (unsigned char Register, unsigned char *Data, unsigned Length)
{
uint8_t buf[2];
epd_cs_low();
buf[0] = 0x70;
buf[1] = Register;
bsp_writeToDisplay(buf, 2);
epd_cs_high();
bsp_delayUs(10);
epd_cs_low();
buf[0] = 0x72;
bsp_writeToDisplay(buf, 1);
bsp_writeToDisplay(Data, Length);
epd_cs_high();
bsp_delayUs(10);
}
void epd_SPI_Send_Byte (uint8_t Register, uint8_t Data)
{
uint8_t buf[2];
epd_cs_low();
buf[0] = 0x70;
buf[1] = Register;
bsp_writeToDisplay(buf, 2);
epd_cs_high();
bsp_delayUs(10);
epd_cs_low();
buf[0] = 0x72;
buf[1] = Data;
bsp_writeToDisplay(buf, 2);
epd_cs_high();
bsp_delayUs(10);
}
void epd_InitDisplayHardware(void)
{
// RST_DIR_OUT;
bsp_pinMode(BSP_PIN_12, BSP_PINMODE_OUTPUT);
// DISCHARGE_DIR_OUT;
bsp_pinMode(BSP_PIN_14, BSP_PINMODE_OUTPUT);
// CS_DIR_OUT;
bsp_pinMode(BSP_PIN_6, BSP_PINMODE_OUTPUT);
// PANELON_DIR_OUT;
bsp_pinMode(BSP_PIN_13, BSP_PINMODE_OUTPUT);
// DRIVERBUSY_DIR_IN;
bsp_pinMode(BSP_PIN_7, BSP_PINMODE_INPUT);
// BORDER_DIR_OUT;
epd_panelon_off();
epd_spi_init();
epd_cs_low();
// epd_pwm_low();
epd_pwm_active(0); //set output low
epd_rst_low();
epd_discharge_low();
// TESTPin_DIR_OUT();
// TESTPin2_DIR_OUT();
}
//************************************************************************
void TestPinLow(void)
{
// TESTPin_Set(0);
}
void TestPinHigh(void)
{
// TESTPin_Set(1);
}
void TestPinTrigger(void)
{
// if(TESTPin_Get())TestPinLow();
// else TestPinHigh();
}
void TestPin2Low(void)
{
// TESTPin2_Set(0);
}
void TestPin2High(void)
{
// TESTPin2_Set(1);
}
void TestPin2Trigger(void)
{
// if(TESTPin2_Get())TestPin2Low();
// else TestPin2High();
}

View File

@ -1,102 +0,0 @@
// Copyright 2013 Pervasive Displays, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.
#ifndef __DISPLAY_HARDWARE_DRIVER_H_
#define __DISPLAY_HARDWARE_DRIVER_H_
/******************************************************************************
* Includes
*****************************************************************************/
#include "bsp.h"
/******************************************************************************
* Defines and typedefs
*****************************************************************************/
//Pin 12 on Serial Expansion Connector
// #define RST_DIR_OUT SEC14_PIN12_SET_OUTP
// #define RST_SET_HIGH SEC14_PIN12_SET_HIGH
// #define RST_SET_LOW SEC14_PIN12_SET_LOW
//Pin 14 on Serial Expansion Connector
// #define DISCHARGE_DIR_OUT SEC14_PIN14_SET_OUTP
// #define DISCHARGE_SET_HIGH SEC14_PIN14_SET_HIGH
// #define DISCHARGE_SET_LOW SEC14_PIN14_SET_LOW
//Pin 6 on Serial Expansion Connector
// #define CS_DIR_OUT SEC14_PIN6_SET_OUTP
// #define CS_SET_HIGH SEC14_PIN6_SET_HIGH
// #define CS_SET_LOW SEC14_PIN6_SET_LOW
//Pin 13 on Serial Expansion Connector
// #define PANELON_DIR_OUT SEC14_PIN13_SET_OUTP
// #define PANELON_SET_HIGH SEC14_PIN13_SET_HIGH
// #define PANELON_SET_LOW SEC14_PIN13_SET_LOW
//Pin 7 on Serial Expansion Connector
// #define DRIVERBUSY_DIR_IN SEC14_PIN7_SET_INP
// #define DRIVERBUSY_GET SEC14_PIN7_INP
//Not implemented
// #define BORDER_DIR_OUT
// #define BORDER_SET_HIGH
// #define BORDER_SET_LOW
//Pin 11 on Serial Expansion Connector
// #define PWM_DIR_OUT SEC14_PIN11_SET_OUTP
// #define PWM_SET_HIGH SEC14_PIN11_SET_HIGH
// #define PWM_SET_LOW SEC14_PIN11_SET_LOW
/******************************************************************************
* Prototypes
*****************************************************************************/
void epd_cs_high(void);
void epd_cs_low(void);
void epd_rst_high(void);
void epd_rst_low(void);
void epd_discharge_high(void);
void epd_discharge_low(void);
void epd_panelon_off(void);
void epd_panelon_on(void);
void epd_pwm_active(uint16_t delayInMs);
void epd_border_high(void);
void epd_border_low(void);
void epd_TestPinLow(void);
void epd_TestPinHigh(void);
void epd_TestPinTrigger(void);
void epd_TestPin2Low(void);
void epd_TestPin2High(void);
void epd_TestPin2Trigger(void);
void epd_delay_ms(uint32_t Time);
int16_t epd_get_temperature(void);
uint32_t epd_GetCurrentTimeTick(void);
/***************************************************************************/
void epd_spi_detach(void);
void epd_spi_init (void);
void epd_SPI_Send (unsigned char Register, unsigned char *Data, unsigned Length);
void epd_SPI_Send_Byte (uint8_t Register, uint8_t Data);
void epd_InitDisplayHardware (void);
/****************************************************************************/
#endif //__DISPLAY_HARDWARE_DRIVER_H_

View File

@ -1,243 +0,0 @@
/*****************************************************************************
*
* Copyright(C) 2012, Embedded Artists AB
* All rights reserved.
*
******************************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* Embedded Artists AB assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. Embedded Artists AB
* reserves the right to make changes in the software without
* notification. Embedded Artists AB also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
*****************************************************************************/
/******************************************************************************
* Includes
*****************************************************************************/
#include "bsp.h"
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <wiringPiSPI.h>
#include <string.h>
/******************************************************************************
* Typedefs and defines
*****************************************************************************/
#define LM75A_I2C_ADDR 0x49 //(0x49 << 1)
#define LM75A_CMD_TEMP 0x00
#define DISPLAY_BUF_SZ (256)
/******************************************************************************
* Local variables
*****************************************************************************/
// I2C device handle
static int gI2cFd = -1;
// mapping between Serial Expansion connector and Raspberry Pi
// GPIOs. Raspberry Pi GPIO numbering according to wiringPi
static int pinMap[BSP_PIN_SZ*2] =
{
// [SEC] | [PI GPIO#]
BSP_PIN_6, 6, // CS
BSP_PIN_7, 0, // Busy
BSP_PIN_8, -1, // Not Used
BSP_PIN_11, 1, // PWM
BSP_PIN_12, 5, // RST
BSP_PIN_13, 3, // PWR_Ctrl
BSP_PIN_14, 4, // DISCHARGE
};
// buffer used when writing to display via SPI
static uint8_t displayBuf[DISPLAY_BUF_SZ];
/******************************************************************************
* Local functions
*****************************************************************************/
static int32_t lm75a_readTemp(void)
{
uint8_t temp[2];
int16_t t = 0;
wiringPiI2CWrite(gI2cFd, LM75A_CMD_TEMP);
temp[0] = wiringPiI2CRead(gI2cFd);
temp[1] = wiringPiI2CRead(gI2cFd);
// 11 MSB bits used. Celcius is calculated as Temp data * 1/8
t = ((temp[0] << 8) | (temp[1]));
return ((t * 100) >> 8);
}
/******************************************************************************
* Public functions
*****************************************************************************/
/******************************************************************************
*
* Description:
* BSP initialize function. Must be called before any other BSP related
* functions.
*
*****************************************************************************/
int bsp_init(void)
{
if (wiringPiSetup() < 0) {
printf("bsp_init: failed to initialize wiringPi\n");
return -1;
}
if ((gI2cFd = wiringPiI2CSetup(LM75A_I2C_ADDR)) < 0) {
printf("bsp_init: failed to initialize I2C\n");
return -1;
}
if (wiringPiSPISetup(0, 1000000) < 0) {
printf("bsp_init: failed to initialize SPI\n");
return -1;
}
return 0;
}
/******************************************************************************
*
* Description:
* Get number of milliseconds
*
*****************************************************************************/
uint32_t bsp_getMsTicks(void)
{
return millis();
}
/******************************************************************************
*
* Description:
* Initialize SPI
*
*****************************************************************************/
void bsp_spiInit(void)
{
// initialized in bsp_init
}
/******************************************************************************
*
* Description:
* Write data to the display
*
*****************************************************************************/
void bsp_writeToDisplay(uint8_t* data, uint16_t len)
{
if (len > DISPLAY_BUF_SZ) {
printf("bsp_writeToDisplay: ERROR len=%d > %d\n", len, DISPLAY_BUF_SZ);
return;
}
memcpy(displayBuf, data, len);
wiringPiSPIDataRW(0, displayBuf, len);
}
/******************************************************************************
*
* Description:
* Delay specified number of milliseconds
*
* Params:
* [in] ms - number of milliseconds to delay
*
*****************************************************************************/
void bsp_delayMs(uint32_t ms)
{
delay(ms);
}
/******************************************************************************
*
* Description:
* Delay specified number of microseconds
*
* Params:
* [in] us - number of microseconds to delay
*
*****************************************************************************/
void bsp_delayUs(uint32_t us)
{
delayMicroseconds(us);
}
/******************************************************************************
*
* Description:
* Read temperature
*
* Params:
* [out] temperature - (int16_t) temperature in Celsius
*
*****************************************************************************/
int16_t bsp_getTemp(void)
{
lm75a_readTemp();
bsp_delayMs(5);
return (int16_t)(lm75a_readTemp()/100);
}
/******************************************************************************
*
* Description:
* Set the PIN mode of a specific pin
*
*****************************************************************************/
void bsp_pinMode(bsp_pin_t pin, bps_pinMode_t mode)
{
int m = INPUT;
int p = 0;
if (pin >= BSP_PIN_SZ) return;
if (mode == BSP_PINMODE_OUTPUT) {
m = OUTPUT;
}
p = pinMap[pin*2+1];
pinMode(p, m);
}
/******************************************************************************
*
* Description:
* Set PIN to high (1) of low (0) value
*
*****************************************************************************/
void bsp_pinOut(bsp_pin_t pin, int value)
{
int p = 0;
int v = LOW;
if (pin >= BSP_PIN_SZ) return;
if (value != 0) {
v = HIGH;
}
p = pinMap[pin*2+1];
digitalWrite(p, v);
}

View File

@ -1,61 +0,0 @@
/*****************************************************************************
*
* Copyright(C) 2012, Embedded Artists AB
* All rights reserved.
*
******************************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* Embedded Artists AB assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. Embedded Artists AB
* reserves the right to make changes in the software without
* notification. Embedded Artists AB also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
*****************************************************************************/
#ifndef __BSP_H__
#define __BSP_H__
/******************************************************************************
* Defines and typedefs
*****************************************************************************/
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
// pin numbering is for the Serial Expansion Connector
typedef enum
{
BSP_PIN_6 = 0,
BSP_PIN_7,
BSP_PIN_8,
BSP_PIN_11,
BSP_PIN_12,
BSP_PIN_13,
BSP_PIN_14,
BSP_PIN_SZ // must be last
} bsp_pin_t;
typedef enum
{
BSP_PINMODE_INPUT = 0,
BSP_PINMODE_OUTPUT
} bps_pinMode_t;
/******************************************************************************
* Prototypes
*****************************************************************************/
int bsp_init(void);
void bsp_spiInit(void);
void bsp_writeToDisplay(uint8_t* data, uint16_t len);
uint32_t bsp_getMsTicks(void);
void bsp_delayMs(uint32_t ms);
void bsp_delayUs(uint32_t us);
int16_t bsp_getTemp(void);
void bsp_pinMode(bsp_pin_t pin, bps_pinMode_t mode);
void bsp_pinOut(bsp_pin_t pin, int value);
#endif //__BSP_H__

View File

@ -16,10 +16,10 @@ using namespace std;
Logic::Logic(const chrono::seconds tokenTimeout, Logic::Logic(const chrono::seconds tokenTimeout,
const string &ldapUri, const string &ldapUri,
const string &bindDN, const string &bindDN,
const string &webPrefix) : const string &webPrefix,
const string &serDev) :
_logger(Logger::get()), _logger(Logger::get()),
_door(Door::get()), _door(serDev),
_epaper(Epaper::get()),
_tokenTimeout(tokenTimeout), _tokenTimeout(tokenTimeout),
_ldapUri(ldapUri), _ldapUri(ldapUri),
_bindDN(bindDN), _bindDN(bindDN),
@ -131,11 +131,11 @@ Logic::Response Logic::_lock()
Logic::Response Logic::_unlock() Logic::Response Logic::_unlock()
{ {
const auto state = _door.state(); const auto oldState = _door.state();
_door.unlock(); _door.unlock();
_createNewToken(false); _createNewToken(false);
if (state == Door::State::Unlocked) if (oldState == Door::State::Unlocked)
{ {
_logger(LogLevel::warning, "Unable to unlock: already unlocked"); _logger(LogLevel::warning, "Unable to unlock: already unlocked");
return AlreadyUnlocked; return AlreadyUnlocked;
@ -211,12 +211,22 @@ out2:
void Logic::_createNewToken(const bool stillValid) void Logic::_createNewToken(const bool stillValid)
{ {
// Todo Mutex einführen
_prevToken = _curToken; _prevToken = _curToken;
_prevValid = stillValid; _prevValid = stillValid;
_curToken = (((uint64_t)rand())<<32) | ((uint64_t)rand()); _curToken = (((uint64_t)rand())<<32) | ((uint64_t)rand());
_epaper.draw(_webPrefix + toHexString(_curToken)); // TODO make things more pretty
const string uri = _webPrefix + toHexString(_curToken);
const int ARRAY_SIZE=1024;
char buffer[ARRAY_SIZE];
snprintf(buffer, ARRAY_SIZE,
"qrencode -l M -d 100 -s 5 \"%s\" -t png -o /tmp/qr.png", uri.c_str());
system(buffer);
ostringstream message; ostringstream message;
message << "New Token generated: " << toHexString(_curToken) << " old Token: " << toHexString(_prevToken) << " is " << (_prevValid?"still":"not") << " valid"; message << "New Token generated: " << toHexString(_curToken) << " old Token: " << toHexString(_prevToken) << " is " << (_prevValid?"still":"not") << " valid";

View File

@ -8,7 +8,6 @@
#include <mutex> #include <mutex>
#include "config.h" #include "config.h"
#include "epaper.h"
#include "door.h" #include "door.h"
#include "logger.h" #include "logger.h"
@ -25,7 +24,8 @@ public:
Logic(const std::chrono::seconds tokenTimeout, Logic(const std::chrono::seconds tokenTimeout,
const std::string &ldapUri, const std::string &ldapUri,
const std::string &bindDN, const std::string &bindDN,
const std::string &webPrefix); const std::string &webPrefix,
const std::string &serDev);
~Logic(); ~Logic();
enum Response { enum Response {
@ -65,10 +65,8 @@ private:
const Logger &_logger; const Logger &_logger;
// Door reference // The door
Door &_door; Door _door;
// Epaper reference
Epaper &_epaper;
// Tokens are 64-bit hexadecimal values // Tokens are 64-bit hexadecimal values
using Token = uint64_t; using Token = uint64_t;

View File

@ -102,6 +102,10 @@ private:
tcp::socket _socket; tcp::socket _socket;
}; };
void emergencyCB()
{
cout << "EMERGENCY!" << endl;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -112,15 +116,10 @@ int main(int argc, char** argv)
string bindDN; string bindDN;
string lockPagePrefix; string lockPagePrefix;
string logfile; string logfile;
string pidFile; string serDev;
bool foreground = false;
l(LogLevel::notice, "Starting doorlockd"); l(LogLevel::notice, "Starting doorlockd");
// Load SPI and I2C modules
system("/usr/bin/gpio load spi");
system("/usr/bin/gpio load i2c");
try { try {
unsigned int timeout; unsigned int timeout;
po::options_description desc("usage: doorlockd"); po::options_description desc("usage: doorlockd");
@ -131,9 +130,8 @@ int main(int argc, char** argv)
("ldap,s", po::value<string>(&ldapUri)->default_value(DEFAULT_LDAP_URI), "Ldap Server") ("ldap,s", po::value<string>(&ldapUri)->default_value(DEFAULT_LDAP_URI), "Ldap Server")
("bidndn,b", po::value<string>(&bindDN)->default_value(DEFAULT_BINDDN), "Bind DN, %s means username") ("bidndn,b", po::value<string>(&bindDN)->default_value(DEFAULT_BINDDN), "Bind DN, %s means username")
("web,w", po::value<string>(&lockPagePrefix)->default_value(DEFAULT_WEB_PREFIX), "Prefix of the webpage") ("web,w", po::value<string>(&lockPagePrefix)->default_value(DEFAULT_WEB_PREFIX), "Prefix of the webpage")
("foreground,f", po::bool_switch(&foreground)->default_value(false), "Run in foreground")
("logfile,l", po::value<string>(&logfile)->default_value(DEFAULT_LOG_FILE), "Log file") ("logfile,l", po::value<string>(&logfile)->default_value(DEFAULT_LOG_FILE), "Log file")
("pid,z", po::value<string>(&pidFile)->default_value(DEFAULT_PID_FILE), "PID file"); ("serial,i", po::value<string>(&serDev)->default_value(DEFAULT_SERIAL_DEVICE), "Serial port");
po::variables_map vm; po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).run(), vm); po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
@ -155,12 +153,10 @@ int main(int argc, char** argv)
goto out; goto out;
} }
daemonize(!foreground, daemonize("/",
"/",
"/dev/null", "/dev/null",
logfile, logfile,
logfile, logfile);
pidFile);
signal(SIGINT, signal_handler); signal(SIGINT, signal_handler);
signal(SIGKILL, signal_handler); signal(SIGKILL, signal_handler);
@ -171,7 +167,8 @@ int main(int argc, char** argv)
logic = unique_ptr<Logic>(new Logic(tokenTimeout, logic = unique_ptr<Logic>(new Logic(tokenTimeout,
ldapUri, ldapUri,
bindDN, bindDN,
lockPagePrefix)); lockPagePrefix,
serDev));
try { try {
server s(io_service, port); server s(io_service, port);
@ -188,7 +185,6 @@ int main(int argc, char** argv)
retval = 0; retval = 0;
out: out:
Door::get().lock();
l(LogLevel::notice, "Doorlockd stopped"); l(LogLevel::notice, "Doorlockd stopped");
return retval; return retval;
} }