feat: RTC collab

This commit is contained in:
susabolca
2024-04-07 23:50:52 +08:00
parent 500359bcb6
commit 6cde0b6781
11 changed files with 190 additions and 72 deletions

View File

@@ -55,7 +55,7 @@ static const uint8_t lut_full_bwr[] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
// 56: LUTR x 7
0x1, VSL|0x1f, 0x0, VSH2|0x3f, 0x0, 0x1, 0xa,
0x1, VSL|0x2f, 0x0, VSH2|0x3f, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -64,7 +64,7 @@ static const uint8_t lut_full_bwr[] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
// 112: LUTW x 7
0x1, VSL|0x2f, 0x0, 0x0, 0x0, 0x1, 0x0,
0x1, VSL|0x3f, 0x0, 0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -73,7 +73,7 @@ static const uint8_t lut_full_bwr[] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
// 168: LUTB x 7
0x1, VSH1|0x37, 0x0, 0x0, 0x0, 0x1, 0x0,
0x1, VSH1|0x2f, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -118,12 +118,18 @@ static void EPD_2IN9_Lut(const unsigned char *lut)
EPD_SSD_SendData(*(lut+232));
}
static void EPD_2IN9_SoftReset()
{
EPD_SSD_SendCommand(0x12); // soft reset
EPD_SSD_WaitBusy(100);
}
static int8_t EPD_2IN9_ReadTemp()
{
int8_t rc;
EPD_SSD_SendCommand(0x12); // soft reset
EPD_SSD_WaitBusy();
//EPD_SSD_SendCommand(0x12); // soft reset
//EPD_SSD_WaitBusy(100);
// Border Waveform
EPD_SSD_SendCommand(0x3C);
@@ -139,7 +145,7 @@ static int8_t EPD_2IN9_ReadTemp()
// Master Activation
EPD_SSD_SendCommand(0x20);
EPD_SSD_WaitBusy();
EPD_SSD_WaitBusy(100);
// read temperature
EPD_SSD_SendCommand(0x1b);
@@ -167,8 +173,8 @@ static void EPD_2IN9_BWR(int width, int height, int left, int top)
int h1 = h0 + height/8 - 1;
// soft reset
EPD_SSD_SendCommand(0x12);
EPD_SSD_WaitBusy();
//EPD_SSD_SendCommand(0x12);
//EPD_SSD_WaitBusy(100);
// Border Waveform
EPD_SSD_SendCommand(0x3C);
@@ -230,7 +236,6 @@ void EPD_2IN9_Display(uint8_t reg)
EPD_SSD_SendCommand(0x22);
EPD_SSD_SendData(reg);
EPD_SSD_SendCommand(0x20);
//EPD_SSD_WaitBusy();
}
void EPD_2IN9_Sleep(void)
@@ -241,17 +246,8 @@ void EPD_2IN9_Sleep(void)
void EPD_SSD_Update(void)
{
static bool need_sleep = 0;
static time_t last = 0;
if (need_sleep) {
if (EPD_SSD_IsBusy()) {
return;
}
EPD_2IN9_Sleep();
need_sleep = 0;
}
time_t now = time(NULL);
if (last && ((now % 60) != 0)) {
return;
@@ -263,10 +259,14 @@ void EPD_SSD_Update(void)
// wakeup EPD
EPD_SSD_Reset();
// create obd
char buf[32];
obdCreateVirtualDisplay(&obd, EPD_WIDTH, EPD_HEIGHT, epd_buffer);
obdFill(&obd, 0, 0);
// soft reset
EPD_2IN9_SoftReset();
// BLE dev name
extern void getBleAdvName(char* buf);
getBleAdvName(buf);
@@ -284,11 +284,9 @@ void EPD_SSD_Update(void)
// temp
epd_temperature = EPD_2IN9_ReadTemp();
const uint8_t fmt[] = {'%', '3', 'u', 0xb0, 'c', '\0'}; // degrees celsius
const char fmt[] = {'%', '3', 'u', 0xb0, 'c', '\0'}; // degrees celsius
System_snprintf(buf, 32, fmt, epd_temperature);
obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_24, 236, 22, buf, 1);
//const uint8_t degree[] = {0xb0, '\0'}; // degrees celsius
//obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_24, 282, 22, degree, 1);
// time
System_snprintf(buf, 32, "%02d:%02d", l->tm_hour, l->tm_min);
@@ -301,22 +299,23 @@ void EPD_SSD_Update(void)
}
// full update every 30 mins
bool full_upd = (l->tm_min == 0 || l->tm_min == 30) ? true : false;
bool full_upd = (l->tm_min == 0) ? true : false;
EPD_2IN9_BWR(EPD_WIDTH, EPD_HEIGHT, 0, 0);
if (!full_upd) EPD_2IN9_Lut(lut_full_bwr);
EPD_2IN9_WriteRam(epd_buffer, EPD_WIDTH, EPD_HEIGHT, 0, 0, 0);
EPD_2IN9_WriteRam(NULL, EPD_WIDTH, EPD_HEIGHT, 0, 0, 1);
// show
EPD_2IN9_Display(full_upd ? 0xf7 : 0xc7); // c7: by REG f7: by OTP b1: no display
need_sleep = 1;
//EPD_SSD_WaitBusy();
//EPD_2IN9_Sleep();
EPD_2IN9_Display(full_upd ? 0xf7 : 0xc7); // c7: by REG f7: by OTP b1: no display
//need_sleep = 1;
EPD_SSD_WaitBusy(15 * 1000);
EPD_2IN9_Sleep();
return;
}
void EPD_SSD_Init(void)
{
EPD_SSD_Reset();
}

View File

@@ -5,6 +5,7 @@
#include <ti/drivers/PIN.h>
#include <ti/sysbios/knl/Clock.h> // Clock_tickPeriod
#include <ti/sysbios/knl/Task.h> // Task_sleep
#include <driverlib/cpu.h> // CPUDelay
#include "epd_driver.h"
@@ -62,7 +63,7 @@ static inline void DEV_Delay_ms(uint16_t t)
static inline void DEV_Delay_us(uint16_t t)
{
while(t--);
CPUdelay(t);
}
static inline void DEV_SPI_WriteByte(uint8_t byte)
@@ -105,9 +106,9 @@ static inline uint8_t DEV_SPI_ReadByte()
void EPD_SSD_Reset()
{
DEV_Digital_Write(EPD_RST_PIN, 0);
DEV_Delay_ms(10);
DEV_Delay_ms(20);
DEV_Digital_Write(EPD_RST_PIN, 1);
DEV_Delay_ms(10);
DEV_Delay_ms(20);
}
void EPD_SSD_SendCommand(uint8_t Reg)
@@ -170,9 +171,10 @@ bool EPD_SSD_IsBusy()
return (DEV_Digital_Read(EPD_BUSY_PIN) == 1);
}
void EPD_SSD_WaitBusy(void)
void EPD_SSD_WaitBusy(uint32_t ms)
{
while (EPD_SSD_IsBusy()) {
for (uint32_t i=0; i<ms; i+=10) {
if (!EPD_SSD_IsBusy()) return;
DEV_Delay_ms(10);
}
}
@@ -239,6 +241,30 @@ uint8_t EPD_BATT_Percent(void)
#endif
#if 1
#include <driverlib/aon_wuc.h>
#include <driverlib/../inc/hw_aux_wuc.h>
// collaborate rtc tick, slow down(<0), speed up(>0)
void RTC_Collaborate( int rtc_collab )
{
uint32_t subSecInc = (0x8000 + rtc_collab) << 8;
// Loading a new RTCSUBSECINC value is done in 5 steps:
// 1. Write bit[15:0] of new SUBSECINC value to AUX_WUC_O_RTCSUBSECINC0
// 2. Write bit[23:16] of new SUBSECINC value to AUX_WUC_O_RTCSUBSECINC1
// 3. Set AUX_WUC_RTCSUBSECINCCTL_UPD_REQ
// 4. Wait for AUX_WUC_RTCSUBSECINCCTL_UPD_ACK
// 5. Clear AUX_WUC_RTCSUBSECINCCTL_UPD_REQ
HWREG( AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINC0 ) = (( subSecInc ) & 0xFFFF );
HWREG( AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINC1 ) = (( subSecInc >> 16 ) & 0xFF );
HWREG( AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINCCTL ) = 1;
while( ! ( HWREGBITW( AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINCCTL, AUX_WUC_RTCSUBSECINCCTL_UPD_ACK_BITN )));
HWREG( AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINCCTL ) = 0;
}
#endif
// should be only called once!
void EPD_Init()
{
@@ -247,6 +273,12 @@ void EPD_Init()
// test LUT size
//lut_size = EPD_LUT_Detect();
// if the rtc ahead 10 seconds per day (24 hours)
// ICALL still using 0x8000 (32768 ticks) for 1 seconds,
// (0x8000 + x) / 0x8000 = (24 * 3600) / (24 * 3600 - 10)
// 32768 * 10 / (24 * 3600) = 3.793
//RTC_Collaborate(-3);
EPD_SSD_Init();
}

View File

@@ -43,11 +43,11 @@ void EPD_SSD_SendData(uint8_t data);
uint8_t EPD_SSD_ReadData();
void EPD_SSD_ReadBytes(uint8_t* buf, uint8_t len);
bool EPD_SSD_IsBusy();
void EPD_SSD_WaitBusy();
void EPD_SSD_WaitBusy(uint32_t ms);
uint8_t EPD_BATT_Percent();
// for epd_inch.c shoule implement,
void EPD_SSD_Init();
void EPD_SSD_Upate();
#endif
#endif

View File

@@ -36,6 +36,10 @@ CONST uint8 EpdTempUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(EPD_TEMP_UUID), HI_UINT16(EPD_TEMP_UUID),
};
CONST uint8 EpdRtcCollabUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(EPD_RTC_COLLAB_UUID), HI_UINT16(EPD_RTC_COLLAB_UUID),
};
static EpdServiceCBs_t *pAppCBs = NULL;
static gattCharCfg_t *EpdDataConfig;
@@ -57,6 +61,9 @@ static uint8 TempProps = GATT_PROP_READ;
//static uint8 TempDesc[] = "Temperature";
static int8 TempVal[1] = {0};
static uint8 RtcCollabProps = GATT_PROP_READ | GATT_PROP_WRITE;
static int8 RtcCollabVal[1] = {0};
static gattAttribute_t EpdServiceAttrTbl[] =
{
// EPD_Service Service Declaration
@@ -97,7 +104,6 @@ static gattAttribute_t EpdServiceAttrTbl[] =
UtcOffVal
},
#if 1
// Characteristic Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
@@ -127,7 +133,21 @@ static gattAttribute_t EpdServiceAttrTbl[] =
0,
TempVal
},
#endif
// Characteristic Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&RtcCollabProps
},
// Characteristic Value
{
{ ATT_BT_UUID_SIZE, EpdRtcCollabUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
RtcCollabVal
},
};
@@ -315,6 +335,13 @@ static bStatus_t EPDService_ReadAttrCB(uint16_t connHandle,
break;
}
case EPD_RTC_COLLAB_UUID: {
int8_t v = RtcCollabVal[0];
*pLen = sizeof(v);
memcpy(pValue, &v, *pLen);
break;
}
default:
return ATT_ERR_ATTR_NOT_FOUND;
}
@@ -356,10 +383,20 @@ static bStatus_t EPDService_WriteAttrCB(uint16_t connHandle,
break;
}
case EPD_RTC_COLLAB_UUID: {
if (len == 1) {
int8_t v = *(int8_t*)pValue;
RTC_Collaborate(v);
RtcCollabVal[0] = v;
}
break;
}
case GATT_CLIENT_CHAR_CFG_UUID:
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY);
break;
default:
return ATT_ERR_ATTR_NOT_FOUND;
}

View File

@@ -7,23 +7,19 @@
#define EPD_SERVICE_SERV_UUID 0xFFF0
// Unix Epoch (from 1970-1-1 00:00)
//#define EPD_EPOCH_ID 0
#define EPD_EPOCH_UUID 0xFFF1
//#define EPD_EPOCH_LEN 4
//#define EPD_EPOCH_LEN_MIN 4
// UTC local time offset
//#define EPD_UTC_OFFSET_ID 1
#define EPD_UTC_OFFSET_UUID 0xFFF2
// battery
//#define EPD_BATT_ID 2
#define EPD_BATT_UUID 0xFFF3
// temperature
//#define EPD_TEMP_ID 3
#define EPD_TEMP_UUID 0xFFF4
// RTC collaboration value
#define EPD_RTC_COLLAB_UUID 0xFFF5
// Callback when a characteristic value has changed
typedef void (*EpdServiceChange_t)(uint16_t connHandle, uint8_t paramID,

View File

@@ -248,4 +248,4 @@ const GFXglyph Dialog_plain_24Glyphs[] = {
{ 2135, 4, 4, 4, 0, -18 } // 0xB0 '°'
};
const GFXfont Dialog_plain_24 = {
(uint8_t *)Dialog_plain_24Bitmaps,(GFXglyph *)Dialog_plain_24Glyphs,0x20, 0xB0, 29};
(uint8_t *)Dialog_plain_24Bitmaps,(GFXglyph *)Dialog_plain_24Glyphs,0x20, 0xB1, 29};

View File

@@ -197,6 +197,7 @@ int main()
#endif //CACHE_AS_RAM
#if !defined( POWER_SAVING ) || defined( USE_FPGA )
#error "don't set."
/* Set constraints for Standby, powerdown and idle mode */
// PowerCC26XX_SB_DISALLOW may be redundant
Power_setConstraint(PowerCC26XX_SB_DISALLOW);
@@ -217,10 +218,10 @@ int main()
/* Kick off profile - Priority 3 */
GAPRole_createTask();
// BLE5 task
// BLE5 task -Priority 2
SimpleBLEPeripheral_createTask();
// EPD task
// EPD task - Priority 1
TaskEPD_createTask();
/* enable interrupts and start SYS/BIOS */

View File

@@ -64,7 +64,7 @@
#define SBP_HCI_CONN_EVT_END_EVT 0x0001
// Task configuration
#define SBP_TASK_PRIORITY 1
#define SBP_TASK_PRIORITY 2
#ifndef SBP_TASK_STACK_SIZE
#define SBP_TASK_STACK_SIZE 644
@@ -950,4 +950,4 @@ void getBleAdvName(char *buf)
{
memcpy(buf, scanRspData+2, 10);
buf[11]='\0';
}
}

View File

@@ -9,31 +9,37 @@
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <util.h>
#include <icall.h>
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"
//#include "board.h"
#include "task_epd.h"
#include "epd_driver.h"
uint8_t VERSION_MAJOR = 0;
uint8_t VERSION_MINOR = 2;
#define EPD_TASK_PRIORITY 2
#define EPD_TASK_PRIORITY 1
#define EPD_TASK_STACK_SIZE 512
Task_Struct EPDTask;
Char EPDTaskStack[EPD_TASK_STACK_SIZE];
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;
// Event globally used to post local events and pend on system and
// local events.
static ICall_SyncHandle syncEvent;
// TBD: need this?
uint32_t epoch_time = 0;
// Event used to control the EPD thread
Event_Struct EPDEvent;
Event_Handle hEPDEvent;
//Event_Handle hEPDEvent;
#define EPDTASK_EVENT_RX_REQUEST Event_Id_00
//#define EPDTASK_EVENT_RX_REQUEST Event_Id_00
#define EPDTASK_EVENT_PERIODIC Event_Id_01
#define EPDTASK_EVENT_ALL ( EPDTASK_EVENT_RX_REQUEST | \
EPDTASK_EVENT_PERIODIC )
#define EPDTASK_EVENT_ALL ( EPDTASK_EVENT_PERIODIC )
static Clock_Struct periodicClock;
@@ -57,11 +63,15 @@ void TaskEPD_createTask(void)
static void EPDTask_clockHandler(UArg arg)
{
Event_post(hEPDEvent, arg);
Event_post(syncEvent, arg);
}
void TaskEPD_taskInit(void)
{
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &syncEvent);
Util_constructClock(&periodicClock, EPDTask_clockHandler,
1000, 0, false, EPDTASK_EVENT_PERIODIC);
EPD_Init();
@@ -70,27 +80,18 @@ void TaskEPD_taskInit(void)
void TaskEPD_taskFxn(UArg a0, UArg a1)
{
Event_Params evParams;
Event_Params_init(&evParams);
Event_construct(&EPDEvent, &evParams);
hEPDEvent = Event_handle(&EPDEvent);
TaskEPD_taskInit();
while (1)
{
UInt events;
events = Event_pend(hEPDEvent,Event_Id_NONE, EPDTASK_EVENT_ALL, BIOS_WAIT_FOREVER);
events = Event_pend(syncEvent, Event_Id_NONE, EPDTASK_EVENT_ALL, ICALL_TIMEOUT_FOREVER);
if (events & EPDTASK_EVENT_RX_REQUEST) {
//if (resp_fram_len) {
// post_epd_response(epd_resp_frame, resp_fram_len);
//}
}
if (events & EPDTASK_EVENT_PERIODIC) {
EPD_Update();
Util_startClock(&periodicClock);
EPD_Update();
}
}
}

View File

@@ -52,3 +52,4 @@ Text.isLoaded = false;
// exception debug
m3Hwi.enableException = true;
m3Hwi.excHandlerFunc = "&execHandlerHook";
halHwi.checkStackFlag = true;

View File

@@ -34,6 +34,7 @@
info('> Found EPD service');
epochCharacter = await epdService.getCharacteristic(0xfff1);
document.getElementById("btnConnect").innerHTML = 'Disconnect';
document.getElementById('etagFn').style.visibility='';
}
}
@@ -44,6 +45,7 @@
info('Disconnected.');
document.getElementById("btnConnect").innerHTML = 'Connect';
document.getElementById('etagFn').style.visibility='hidden';
}
async function doSetTime() {
@@ -55,6 +57,45 @@
info("Write unix epoch: " + epoch);
}
async function doReadEtag() {
var host_epoch = Date.now() / 1000 | 0;
// read current time
var chr = await epdService.getCharacteristic(0xfff1);
var epoch = (await chr.readValue()).getUint32(0, 1);
// read time zone
var chr = await epdService.getCharacteristic(0xfff2);
var tz_min = (await chr.readValue()).getInt32(0, 1);
info(`# host time: ${host_epoch}, diff (${epoch - host_epoch}) seconds.`);
info(`# etag time: ${epoch}, tz: ${tz_min} minutes of UTC.`);
// battery
var chr = await epdService.getCharacteristic(0xfff3);
var batt = (await chr.readValue()).getUint16(0, 1);
// Temperature
var chr = await epdService.getCharacteristic(0xfff4);
var temp = (await chr.readValue()).getInt8(0, 1);
info(`# etag sensor: battery(${batt}mv), temperature(${temp}'C). `);
// RTC Collaborate
var chr = await epdService.getCharacteristic(0xfff5);
var rtc_collab = (await chr.readValue()).getInt8(0, 1);
info(`# rtc collab: ${rtc_collab} every 1 second.`);
}
async function doRtcCollab() {
var col = prompt("对 32.768kHz 晶振补偿频漂,走时快补偿负数,走时慢补偿正数。可选范围 (-3 ~ 3)", 0);
if (col == null || col < -3 || col > 3) return;
var chr = await epdService.getCharacteristic(0xfff5);
var buf = new ArrayBuffer(1);
var arr = new Int8Array(buf);
arr[0] = parseInt(col);
await chr.writeValueWithResponse(arr);
info(`write RTC collabration: ${col}`);
}
function info(logTXT) {
var today = new Date();
var time = ("0" + today.getHours()).slice(-2) + ":" + ("0" + today.getMinutes()).slice(-2) + ":" + ("0" + today.getSeconds()).slice(-2) + " : ";
@@ -67,8 +108,18 @@
}
</script>
<button id="btnConnect" type="button" onclick="doConnect()">Connect</button>
<p>
<label> Choose </label>
<button id="btnConnect" type="button" onclick="doConnect()">Connect</button>
</p>
<p id="etagFn" style="visibility:hidden;">
<button id="btnReadEtag" type="button" onclick="doReadEtag()">ReadEtag</button>
<button id="btnSetTime" type="button" onclick="doSetTime()">SetTime</button>
<div id="log"></div>
<button id="btnRtcCollab" type="button" onclick="doRtcCollab()">RtcCollab</button>
</p>
<p>
<div id="log">
CC2640R2-ETAG Webtool. <br/>
</div>
</p>
</html>