mirror of
https://github.com/binary-kitchen/doorlockd
synced 2024-12-22 10:24:26 +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:
parent
b4d6a46025
commit
73868b2d4d
@ -15,7 +15,7 @@
|
||||
#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_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"
|
||||
|
||||
|
@ -11,12 +11,10 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
void daemonize(const bool daemonize,
|
||||
const string &dir,
|
||||
void daemonize(const string &dir,
|
||||
const string &stdinfile,
|
||||
const string &stdoutfile,
|
||||
const string &stderrfile,
|
||||
const string &pidFile)
|
||||
const string &stderrfile)
|
||||
{
|
||||
umask(0);
|
||||
|
||||
@ -26,24 +24,6 @@ void daemonize(const bool daemonize,
|
||||
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)
|
||||
{
|
||||
throw runtime_error(strerror(errno));
|
||||
|
@ -8,11 +8,9 @@
|
||||
//
|
||||
// This function will also redirect stdin, out and err to the
|
||||
// specified files
|
||||
void daemonize(const bool daemonize,
|
||||
const std::string &dir,
|
||||
void daemonize(const std::string &dir,
|
||||
const std::string &stdinfile,
|
||||
const std::string &stdoutfile,
|
||||
const std::string &stderrfile,
|
||||
const std::string &pidFile);
|
||||
const std::string &stderrfile);
|
||||
|
||||
#endif
|
||||
|
@ -1,35 +1,89 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <wiringPi.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "logger.h"
|
||||
#include "door.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Door::Door() :
|
||||
_l(Logger::get())
|
||||
Door::Door(const std::string &serDev,
|
||||
unsigned int baudrate) :
|
||||
_baudrate(baudrate),
|
||||
_port(_ioService, serDev),
|
||||
_logger(Logger::get())
|
||||
{
|
||||
_l(LogLevel::info, "Initializing Raspberry Pi GPIOs");
|
||||
wiringPiSetup();
|
||||
pinMode(_HEARTBEATPIN, OUTPUT);
|
||||
pinMode(_SCHNAPPERPIN, OUTPUT);
|
||||
pinMode(_LOCKPIN, INPUT);
|
||||
pullUpDnControl(_LOCKPIN, PUD_UP);
|
||||
lock();
|
||||
// Configure serial port
|
||||
_port.set_option(boost::asio::serial_port_base::baud_rate(baudrate));
|
||||
_port.set_option(boost::asio::serial_port_base::character_size(8));
|
||||
_port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
|
||||
_port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
|
||||
_port.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
|
||||
|
||||
_asyncRead();
|
||||
|
||||
_ioThread = std::thread([this] () {
|
||||
_ioService.run();
|
||||
});
|
||||
|
||||
// TODO Ping device
|
||||
}
|
||||
|
||||
Door::~Door()
|
||||
{
|
||||
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;
|
||||
return d;
|
||||
std::unique_lock<std::mutex> lock(_receiveLock);
|
||||
_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
|
||||
@ -39,97 +93,66 @@ Door::State Door::state() const
|
||||
|
||||
void Door::lock()
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_mutex);
|
||||
_stateMutex.lock();
|
||||
|
||||
_l(LogLevel::notice, "Executing Pre Lock Script");
|
||||
system(PRE_LOCK_SCRIPT);
|
||||
|
||||
digitalWrite(_SCHNAPPERPIN, HIGH);
|
||||
_l(LogLevel::info, "Door closed");
|
||||
|
||||
if (_state == State::Unlocked)
|
||||
{
|
||||
// Stop the Heartbeat Thread
|
||||
_state = State::Locked;
|
||||
_heartbeat.join();
|
||||
if (_state == State::Locked) {
|
||||
_stateMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
_l(LogLevel::notice, "Executing Post Lock Script");
|
||||
system(POST_LOCK_SCRIPT);
|
||||
_state = State::Locked;
|
||||
_stateMutex.unlock();
|
||||
_heartbeatCondition.notify_one();
|
||||
_heartbeatThread.join();
|
||||
}
|
||||
|
||||
void Door::unlock()
|
||||
{
|
||||
_l(LogLevel::notice, "Executing Pre Unlock Script");
|
||||
system(PRE_UNLOCK_SCRIPT);
|
||||
|
||||
// In any case, klacker the schnapper
|
||||
_stateMutex.lock();
|
||||
_schnapper = true;
|
||||
|
||||
// If heartbeat is already running, return
|
||||
if (_state == State::Unlocked)
|
||||
{
|
||||
if(_state == State::Unlocked) {
|
||||
_stateMutex.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, first set state to unlocked
|
||||
_state = State::Unlocked;
|
||||
_stateMutex.unlock();
|
||||
|
||||
// Start the Heartbeat Thread
|
||||
_heartbeat = std::thread([this] () {
|
||||
_heartbeatThread = 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) {
|
||||
if (_state == State::Unlocked) {
|
||||
writeCMD('u');
|
||||
|
||||
// In case of schnapper, send 0x55 resp. 0xaa to the schnapperpin
|
||||
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
|
||||
if (_schnapper) {
|
||||
_schnapper = false;
|
||||
}
|
||||
|
||||
// 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);
|
||||
writeCMD('s');
|
||||
}
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -2,64 +2,69 @@
|
||||
#define DOOR_H
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/serial_port.hpp>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
|
||||
class Door final
|
||||
{
|
||||
public:
|
||||
|
||||
// Returns the singleton
|
||||
static Door &get();
|
||||
Door(const std::string &serDev,
|
||||
unsigned int baudrate = 9600);
|
||||
~Door();
|
||||
|
||||
enum class State {Locked, Unlocked};
|
||||
enum class State {Unlocked, Locked};
|
||||
|
||||
// Current state of the door
|
||||
State state() const;
|
||||
|
||||
// Lock the door
|
||||
void lock();
|
||||
// Unlock the door
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
|
||||
Door();
|
||||
using Milliseconds = std::chrono::milliseconds;
|
||||
|
||||
// used for logging
|
||||
const Logger &_l;
|
||||
const unsigned int _baudrate;
|
||||
|
||||
// Indicates the internal state: Door is open or locked
|
||||
volatile State _state = { Door::State::Locked };
|
||||
// To prevent concurrent writes
|
||||
std::mutex _serialMutex = { };
|
||||
|
||||
// A Heartbeat thread is started when the door is unlocked
|
||||
std::thread _heartbeat = { };
|
||||
boost::asio::io_service _ioService = { };
|
||||
boost::asio::serial_port _port;
|
||||
|
||||
// Read by the Heartbeat thread if it should klacker the schnapper or not
|
||||
bool _schnapper = { false };
|
||||
std::mutex _stateMutex = { };
|
||||
volatile State _state = { State::Locked };
|
||||
|
||||
// Mutex to avoid concurrent locks
|
||||
std::mutex _mutex = { };
|
||||
std::thread _heartbeatThread = { };
|
||||
std::mutex _heartbeatMutex = { };
|
||||
std::condition_variable _heartbeatCondition = { };
|
||||
|
||||
// WiringPi GPIO Pins
|
||||
static constexpr int _HEARTBEATPIN = 10;
|
||||
static constexpr int _SCHNAPPERPIN = 7;
|
||||
static constexpr int _LOCKPIN = 15;
|
||||
std::thread _ioThread = { };
|
||||
void _asyncRead();
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_
|
@ -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();
|
||||
}
|
||||
|
@ -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_
|
@ -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();
|
||||
}
|
@ -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_
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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__
|
@ -16,10 +16,10 @@ using namespace std;
|
||||
Logic::Logic(const chrono::seconds tokenTimeout,
|
||||
const string &ldapUri,
|
||||
const string &bindDN,
|
||||
const string &webPrefix) :
|
||||
const string &webPrefix,
|
||||
const string &serDev) :
|
||||
_logger(Logger::get()),
|
||||
_door(Door::get()),
|
||||
_epaper(Epaper::get()),
|
||||
_door(serDev),
|
||||
_tokenTimeout(tokenTimeout),
|
||||
_ldapUri(ldapUri),
|
||||
_bindDN(bindDN),
|
||||
@ -131,11 +131,11 @@ Logic::Response Logic::_lock()
|
||||
|
||||
Logic::Response Logic::_unlock()
|
||||
{
|
||||
const auto state = _door.state();
|
||||
const auto oldState = _door.state();
|
||||
_door.unlock();
|
||||
_createNewToken(false);
|
||||
|
||||
if (state == Door::State::Unlocked)
|
||||
if (oldState == Door::State::Unlocked)
|
||||
{
|
||||
_logger(LogLevel::warning, "Unable to unlock: already unlocked");
|
||||
return AlreadyUnlocked;
|
||||
@ -211,12 +211,22 @@ out2:
|
||||
|
||||
void Logic::_createNewToken(const bool stillValid)
|
||||
{
|
||||
// Todo Mutex einführen
|
||||
|
||||
_prevToken = _curToken;
|
||||
_prevValid = stillValid;
|
||||
|
||||
_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;
|
||||
message << "New Token generated: " << toHexString(_curToken) << " old Token: " << toHexString(_prevToken) << " is " << (_prevValid?"still":"not") << " valid";
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <mutex>
|
||||
|
||||
#include "config.h"
|
||||
#include "epaper.h"
|
||||
#include "door.h"
|
||||
#include "logger.h"
|
||||
|
||||
@ -25,7 +24,8 @@ public:
|
||||
Logic(const std::chrono::seconds tokenTimeout,
|
||||
const std::string &ldapUri,
|
||||
const std::string &bindDN,
|
||||
const std::string &webPrefix);
|
||||
const std::string &webPrefix,
|
||||
const std::string &serDev);
|
||||
~Logic();
|
||||
|
||||
enum Response {
|
||||
@ -65,10 +65,8 @@ private:
|
||||
|
||||
const Logger &_logger;
|
||||
|
||||
// Door reference
|
||||
Door &_door;
|
||||
// Epaper reference
|
||||
Epaper &_epaper;
|
||||
// The door
|
||||
Door _door;
|
||||
|
||||
// Tokens are 64-bit hexadecimal values
|
||||
using Token = uint64_t;
|
||||
|
@ -102,6 +102,10 @@ private:
|
||||
tcp::socket _socket;
|
||||
};
|
||||
|
||||
void emergencyCB()
|
||||
{
|
||||
cout << "EMERGENCY!" << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@ -112,15 +116,10 @@ int main(int argc, char** argv)
|
||||
string bindDN;
|
||||
string lockPagePrefix;
|
||||
string logfile;
|
||||
string pidFile;
|
||||
bool foreground = false;
|
||||
string serDev;
|
||||
|
||||
l(LogLevel::notice, "Starting doorlockd");
|
||||
|
||||
// Load SPI and I2C modules
|
||||
system("/usr/bin/gpio load spi");
|
||||
system("/usr/bin/gpio load i2c");
|
||||
|
||||
try {
|
||||
unsigned int timeout;
|
||||
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")
|
||||
("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")
|
||||
("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")
|
||||
("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::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
|
||||
@ -155,12 +153,10 @@ int main(int argc, char** argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
daemonize(!foreground,
|
||||
"/",
|
||||
daemonize("/",
|
||||
"/dev/null",
|
||||
logfile,
|
||||
logfile,
|
||||
pidFile);
|
||||
logfile);
|
||||
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGKILL, signal_handler);
|
||||
@ -171,7 +167,8 @@ int main(int argc, char** argv)
|
||||
logic = unique_ptr<Logic>(new Logic(tokenTimeout,
|
||||
ldapUri,
|
||||
bindDN,
|
||||
lockPagePrefix));
|
||||
lockPagePrefix,
|
||||
serDev));
|
||||
|
||||
try {
|
||||
server s(io_service, port);
|
||||
@ -188,7 +185,6 @@ int main(int argc, char** argv)
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
Door::get().lock();
|
||||
l(LogLevel::notice, "Doorlockd stopped");
|
||||
return retval;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user