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:
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_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"
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
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";
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user