1
0
mirror of https://github.com/binary-kitchen/doorlockd synced 2024-11-16 20:19:13 +01:00
doorlockd-mirror/epaper/Display_COG_Process.c
2015-05-10 22:18:22 +00:00

651 lines
19 KiB
C

// 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();
}