mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 07:06:36 +01:00
Added 1.54" Tag-AP support as virtual tag
This commit is contained in:
BIN
binaries/AP_FW_1.54.bin
Normal file
BIN
binaries/AP_FW_1.54.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -19,10 +19,12 @@
|
||||
#include "uart.h"
|
||||
#include "wdt.h"
|
||||
|
||||
// #if (HAS_SCREEN == 1)
|
||||
|
||||
uint8_t updateCount = 1;
|
||||
extern uint8_t __xdata curChannel;
|
||||
extern uint8_t __xdata curPendingData;
|
||||
extern uint8_t __xdata curNoUpdate;
|
||||
|
||||
#if (SCREEN_WIDTH == 1)
|
||||
void epdInitialize() {
|
||||
epdEnable();
|
||||
pr("Setting up EPD\n");
|
||||
@@ -36,11 +38,6 @@ void epdInitialize() {
|
||||
timerDelay(1333);
|
||||
}
|
||||
|
||||
extern uint8_t __xdata curChannel;
|
||||
|
||||
extern uint8_t __xdata curPendingData;
|
||||
extern uint8_t __xdata curNoUpdate;
|
||||
|
||||
void epdShowRun() {
|
||||
epdClear();
|
||||
epdSetPos(0);
|
||||
@@ -71,4 +68,28 @@ void epdShowRun() {
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (SCREEN_WIDTH != 1)
|
||||
|
||||
void epdInitialize() {
|
||||
epdConfigGPIO(true);
|
||||
spiInit();
|
||||
epdSetup();
|
||||
}
|
||||
|
||||
void epdShowRun() {
|
||||
// return;
|
||||
wdt60s();
|
||||
selectLUT(EPD_LUT_NO_REPEATS);
|
||||
clearScreen();
|
||||
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
|
||||
epdPrintBegin(16, 55, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
|
||||
epdpr("AP Mode");
|
||||
epdPrintEnd();
|
||||
drawNoWait();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,8 @@ BUILD ?= zbs29v033
|
||||
SOURCES += main.c
|
||||
SOURCES += comms.c
|
||||
SOURCES += APDisplay.c
|
||||
SOURCES += barcode.c
|
||||
SOURCES += emulateTag.c
|
||||
|
||||
all: #make sure it is the first target
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ $stackdisturbed = false;
|
||||
$mem = checkmem();
|
||||
while(1){
|
||||
$errlist = array();
|
||||
exec("make BUILD=zbs29v033 CPU=8051 SOC=zbs243 2>&1 | grep error | grep -v make", $errlist);
|
||||
exec("make BUILD=zbs154v033 CPU=8051 SOC=zbs243 2>&1 | grep error | grep -v make", $errlist);
|
||||
if(checkmem()!=$mem){
|
||||
$stackdisturbed = true;
|
||||
echo "Stack size was $mem, is now ".checkmem()." !!!\n";
|
||||
|
||||
@@ -12,7 +12,7 @@ make BUILD=zbs_nodisplay CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/AP_FW_Nodisplay.bin -v
|
||||
make clean > /dev/null
|
||||
|
||||
echo -e "\n\nBuilding 2.9 version..."
|
||||
make BUILD=zbs29v033 CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/AP_FW_2.9.bin -v
|
||||
echo -e "\n\nBuilding 1.54 version..."
|
||||
make BUILD=zbs154v033 CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/AP_FW_1.54.bin -v
|
||||
make clean > /dev/null
|
||||
|
||||
124
zbs243_AP_FW/emulateTag.c
Executable file
124
zbs243_AP_FW/emulateTag.c
Executable file
@@ -0,0 +1,124 @@
|
||||
#define __packed
|
||||
#include "board.h"
|
||||
|
||||
#if (HAS_SCREEN == 1 && AP_EMULATE_TAG == 1)
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asmUtil.h"
|
||||
#include "comms.h"
|
||||
#include "cpu.h"
|
||||
#include "printf.h"
|
||||
#include "proto.h"
|
||||
#include "radio.h"
|
||||
#include "screen.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
#include "wdt.h"
|
||||
|
||||
extern uint8_t __xdata fakeTagMac[8] = {0x0, 0x00, 0x55, 0xCE, 0xAC, 0x00, 0x00};
|
||||
extern uint8_t __xdata radiorxbuffer[];
|
||||
extern uint8_t __xdata blockbuffer[];
|
||||
extern void espNotifyAvailDataReq(const struct AvailDataReq *adr, const uint8_t *src);
|
||||
extern void espBlockRequest(const struct blockRequest *br);
|
||||
extern void espNotifyXferComplete(const uint8_t *src);
|
||||
|
||||
extern void addCRC(void *p, uint8_t len);
|
||||
bool __xdata fakeTagTrafficPending = false;
|
||||
|
||||
static struct AvailDataInfo __xdata ad;
|
||||
static uint8_t blockCount = 0;
|
||||
static uint32_t __xdata lastRequest = 0;
|
||||
static bool dataRequested = false;
|
||||
|
||||
static bool validateBlockData() {
|
||||
struct blockData *bd = (struct blockData *)blockbuffer;
|
||||
// pr("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum);
|
||||
uint16_t t = 0;
|
||||
for (uint16_t c = 0; c < bd->size; c++) {
|
||||
t += bd->data[c];
|
||||
}
|
||||
return bd->checksum == t;
|
||||
}
|
||||
|
||||
uint16_t epdByteCounter = 0;
|
||||
void epdWriteByte(uint8_t b) {
|
||||
epdSend(b);
|
||||
epdByteCounter++;
|
||||
// check if we need to switch to a
|
||||
if (epdByteCounter == (SCREEN_HEIGHT * SCREEN_WIDTH / 8)) {
|
||||
epdDeselect();
|
||||
endWriteFramebuffer();
|
||||
beginWriteFramebuffer(EPD_COLOR_RED);
|
||||
epdSelect();
|
||||
}
|
||||
}
|
||||
|
||||
void fakeTagGetData() {
|
||||
if ((timerGet() - lastRequest) > (1200UL * 1333)) {
|
||||
if (dataRequested == false) {
|
||||
if (ad.dataSize) {
|
||||
struct blockRequest br;
|
||||
br.blockId = blockCount;
|
||||
br.ver = ad.dataVer;
|
||||
espBlockRequest(&br);
|
||||
dataRequested = true;
|
||||
}
|
||||
} else {
|
||||
if (validateBlockData()) {
|
||||
struct blockData *bd = (struct blockData *)blockbuffer;
|
||||
if (blockCount == 0) {
|
||||
epdByteCounter = 0;
|
||||
clearScreen();
|
||||
selectLUT(ad.dataTypeArgument % 3);
|
||||
beginFullscreenImage();
|
||||
beginWriteFramebuffer(EPD_COLOR_BLACK);
|
||||
epdSelect();
|
||||
}
|
||||
for (uint16_t c = 0; c < bd->size; c++) {
|
||||
epdWriteByte(bd->data[c]);
|
||||
}
|
||||
ad.dataSize -= bd->size;
|
||||
blockCount++;
|
||||
} else {
|
||||
// request data again!
|
||||
}
|
||||
if (ad.dataSize) {
|
||||
} else {
|
||||
epdDeselect();
|
||||
endWriteFramebuffer();
|
||||
espNotifyXferComplete(fakeTagMac);
|
||||
fakeTagTrafficPending = false;
|
||||
drawNoWait();
|
||||
}
|
||||
dataRequested = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fakePendingData(struct pendingData *pd) {
|
||||
if ((pd->availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP) || (pd->availdatainfo.dataType == DATATYPE_IMG_RAW_2BPP) || (pd->availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP_DIRECT)) {
|
||||
memcpy(&ad, &(pd->availdatainfo), sizeof(struct AvailDataInfo));
|
||||
blockCount = 0;
|
||||
fakeTagTrafficPending = true;
|
||||
dataRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
void fakeTagCheckIn() {
|
||||
struct AvailDataReq *adr = (struct AvailDataReq *)radiorxbuffer;
|
||||
|
||||
memset(adr, 0, sizeof(struct AvailDataReq));
|
||||
adr->batteryMv = 1337;
|
||||
adr->hwType = HW_TYPE;
|
||||
adr->lastPacketLQI = 100;
|
||||
adr->lastPacketRSSI = 100;
|
||||
adr->wakeupReason = 0;
|
||||
addCRC(adr, sizeof(struct AvailDataReq));
|
||||
espNotifyAvailDataReq(adr, fakeTagMac);
|
||||
}
|
||||
|
||||
#endif
|
||||
11
zbs243_AP_FW/emulateTag.h
Executable file
11
zbs243_AP_FW/emulateTag.h
Executable file
@@ -0,0 +1,11 @@
|
||||
#ifndef _AP_EMULATE_H_
|
||||
#define _AP_EMULATE_H_
|
||||
|
||||
void fakeTagCheckIn();
|
||||
|
||||
extern uint8_t __xdata fakeTagMac[8];
|
||||
extern bool __xdata fakeTagTrafficPending;
|
||||
extern void fakePendingData(struct pendingData* pd);
|
||||
extern void fakeTagGetData();
|
||||
|
||||
#endif
|
||||
@@ -20,6 +20,10 @@
|
||||
#include "APDisplay.h"
|
||||
#endif
|
||||
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
#include "emulateTag.h"
|
||||
#endif
|
||||
|
||||
#define MAX_PENDING_MACS 50
|
||||
#define HOUSEKEEPING_INTERVAL 60UL
|
||||
|
||||
@@ -75,6 +79,8 @@ uint8_t seq = 0; // holds current seque
|
||||
uint8_t __xdata blockbuffer[BLOCK_XFER_BUFFER_SIZE + 5]; // block transfer buffer
|
||||
uint8_t lastAckMac[8] = {0};
|
||||
|
||||
uint8_t *__xdata blockXferBuffer = blockbuffer;
|
||||
|
||||
// these variables hold the current mac were talking to
|
||||
#define CONCURRENT_REQUEST_DELAY 1200UL * TIMER_TICKS_PER_MS
|
||||
uint32_t __xdata lastBlockRequest = 0;
|
||||
@@ -211,7 +217,7 @@ void countSlots() {
|
||||
extern uint8_t *__idata blockp;
|
||||
void processSerial(uint8_t lastchar) {
|
||||
static uint32_t __xdata lastSerial = 0;
|
||||
if((timerGet() - lastSerial)>(TIMER_TICKS_PER_MS*25)){
|
||||
if ((timerGet() - lastSerial) > (TIMER_TICKS_PER_MS * 25)) {
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
lastSerial = timerGet();
|
||||
} else {
|
||||
@@ -262,14 +268,23 @@ void processSerial(uint8_t lastchar) {
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
|
||||
struct pendingData *pd = (struct pendingData *)serialbuffer;
|
||||
int8_t slot = findSlotForMac(pd->targetMac);
|
||||
if (slot == -1) slot = findFreeSlot();
|
||||
if (slot != -1) {
|
||||
xMemCopyShort(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
if (memcmp(pd->targetMac, fakeTagMac, 8) == 0) {
|
||||
fakePendingData(pd);
|
||||
pr("ACK>\n");
|
||||
} else {
|
||||
pr("NOQ>\n");
|
||||
#endif
|
||||
int8_t slot = findSlotForMac(pd->targetMac);
|
||||
if (slot == -1) slot = findFreeSlot();
|
||||
if (slot != -1) {
|
||||
xMemCopyShort(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
|
||||
pr("ACK>\n");
|
||||
} else {
|
||||
pr("NOQ>\n");
|
||||
}
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
pr("NOK>\n");
|
||||
}
|
||||
@@ -284,8 +299,17 @@ void processSerial(uint8_t lastchar) {
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
|
||||
struct pendingData *pd = (struct pendingData *)serialbuffer;
|
||||
deleteAllPendingDataForVer((uint8_t *)&pd->availdatainfo.dataVer);
|
||||
pr("ACK>\n");
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
if (memcmp(pd->targetMac, fakeTagMac, 8) == 0) {
|
||||
fakeTagTrafficPending = false;
|
||||
pr("ACK>\n");
|
||||
} else {
|
||||
#endif
|
||||
deleteAllPendingDataForVer((uint8_t *)&pd->availdatainfo.dataVer);
|
||||
pr("ACK>\n");
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
pr("NOK>\n");
|
||||
}
|
||||
@@ -367,10 +391,9 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
// mark this mac as the new current mac we're talking to
|
||||
xMemCopyShort((void *__xdata)lastBlockMac, (void *__xdata)rxHeader->src, 8);
|
||||
lastBlockRequest = timerGet();
|
||||
// memcpy(lastBlockRequest, rxHeader->src, 8);
|
||||
} else {
|
||||
// we're talking to another mac, let this mac know we can't accomodate another request right now
|
||||
pr("not accepting traffic from this tag\n");
|
||||
pr("BUSY!\n");
|
||||
sendCancelXfer(rxHeader->src);
|
||||
return;
|
||||
}
|
||||
@@ -594,13 +617,40 @@ void sendPong(void *__xdata buf) {
|
||||
radioTx(radiotxbuffer);
|
||||
}
|
||||
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
void attemptFakeTagUpdate() {
|
||||
if (memcmp(fakeTagMac, lastBlockMac, 8) == 0) {
|
||||
lastBlockRequest = timerGet();
|
||||
fakeTagGetData();
|
||||
} else {
|
||||
// we weren't talking to this mac, see if there was a transfer in progress from another mac, recently
|
||||
if ((timerGet() - lastBlockRequest) > CONCURRENT_REQUEST_DELAY) {
|
||||
// mark this mac as the new current mac we're talking to
|
||||
xMemCopyShort((void *__xdata)lastBlockMac, (void *__xdata)fakeTagMac, 8);
|
||||
lastBlockRequest = timerGet();
|
||||
fakeTagGetData();
|
||||
} else {
|
||||
// we're talking to another mac, let this mac know we can't accomodate another request right now
|
||||
pr("FAKE TAG BUSY!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// main loop
|
||||
void main(void) {
|
||||
clockingAndIntsInit();
|
||||
timerInit();
|
||||
boardInit();
|
||||
|
||||
P0FUNC = 0b11001111; // enable uart tx/rx and SPI bus functions
|
||||
|
||||
uartInit();
|
||||
|
||||
#if (HAS_SCREEN == 1)
|
||||
epdInitialize();
|
||||
#endif
|
||||
|
||||
irqsOn();
|
||||
wdt60s();
|
||||
|
||||
@@ -617,10 +667,6 @@ void main(void) {
|
||||
radioInit();
|
||||
radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID);
|
||||
|
||||
#if (HAS_SCREEN == 1)
|
||||
epdInitialize();
|
||||
#endif
|
||||
|
||||
// init the "random" number generation unit
|
||||
rndSeed(mSelfMac[0] ^ (uint8_t)timerGetLowBits(), mSelfMac[1]);
|
||||
radioSetChannel(curChannel);
|
||||
@@ -689,10 +735,15 @@ void main(void) {
|
||||
}
|
||||
loopCount--;
|
||||
if (loopCount == 0) {
|
||||
#if (HAS_SCREEN == 1)
|
||||
#if (HAS_SCREEN == 1)
|
||||
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
if (fakeTagTrafficPending) attemptFakeTagUpdate();
|
||||
#else
|
||||
countSlots();
|
||||
epdShowRun();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
wdt60s();
|
||||
loopCount = 10000;
|
||||
// every once in a while, especially when handling a lot of traffic, the radio will hang. Calling this every once in while
|
||||
@@ -700,7 +751,9 @@ void main(void) {
|
||||
RADIO_command = RADIO_CMD_RECEIVE;
|
||||
}
|
||||
}
|
||||
|
||||
#if (AP_EMULATE_TAG == 1)
|
||||
fakeTagCheckIn();
|
||||
#endif
|
||||
for (uint8_t __xdata c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (pendingDataArr[c].attemptsLeft == 1) {
|
||||
espNotifyTimeOut(pendingDataArr[c].targetMac);
|
||||
@@ -712,4 +765,4 @@ void main(void) {
|
||||
}
|
||||
housekeepingTimer = timerGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
#!/bin/bash
|
||||
make clean
|
||||
make clean > /dev/null
|
||||
|
||||
make BUILD=zbs154v033 CPU=8051 SOC=zbs243
|
||||
mv main.bin ../binaries/Tag_FW_1.54.bin
|
||||
make clean
|
||||
echo -e "\nBuilding 1.54 version..."
|
||||
make BUILD=zbs154v033 CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/Tag_FW_1.54.bin -v
|
||||
make clean > /dev/null
|
||||
|
||||
make BUILD=zbs29v033 CPU=8051 SOC=zbs243
|
||||
mv main.bin ../binaries/Tag_FW_2.9.bin
|
||||
make clean
|
||||
echo -e "\n\nBuilding 2.9 (SSD1619) version..."
|
||||
make BUILD=zbs29v033 CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/Tag_FW_2.9.bin -v
|
||||
make clean > /dev/null
|
||||
|
||||
make BUILD=zbs42v033 CPU=8051 SOC=zbs243
|
||||
mv main.bin ../binaries/Tag_FW_4.2.bin
|
||||
make clean
|
||||
echo -e "\n\nBuilding 4.2 version..."
|
||||
make BUILD=zbs42v033 CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/Tag_FW_4.2.bin -v
|
||||
make clean > /dev/null
|
||||
|
||||
make BUILD=zbs29_uc8151 CPU=8051 SOC=zbs243
|
||||
mv main.bin ../binaries/Tag_FW_2.9-uc8151.bin
|
||||
make clean
|
||||
echo -e "\n\nBuilding 2.9 (UC8151) version..."
|
||||
make BUILD=zbs29_uc8151 CPU=8051 SOC=zbs243 > /dev/null
|
||||
mv main.bin ../binaries/Tag_FW_2.9-uc8151.bin -v
|
||||
make clean > /dev/null
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "lut.h"
|
||||
#include "printf.h"
|
||||
#include "screen.h"
|
||||
#include "settings.h"
|
||||
//#include "settings.h"
|
||||
#include "sleep.h"
|
||||
#include "spi.h"
|
||||
#include "timer.h"
|
||||
|
||||
1
zbs243_shared/board/zbs154v033/board.h
Normal file → Executable file
1
zbs243_shared/board/zbs154v033/board.h
Normal file → Executable file
@@ -22,6 +22,7 @@
|
||||
|
||||
#define HAS_EEPROM 1
|
||||
#define HAS_SCREEN 1
|
||||
#define AP_EMULATE_TAG 1
|
||||
|
||||
//hw types
|
||||
#define HW_TYPE SOLUM_154_033
|
||||
|
||||
1
zbs243_shared/board/zbs29_uc8151/board.h
Normal file → Executable file
1
zbs243_shared/board/zbs29_uc8151/board.h
Normal file → Executable file
@@ -21,6 +21,7 @@
|
||||
|
||||
#define HAS_EEPROM 1
|
||||
#define HAS_SCREEN 1
|
||||
#define AP_EMULATE_TAG 1
|
||||
|
||||
//hw types
|
||||
#define HW_TYPE SOLUM_29_033
|
||||
|
||||
1
zbs243_shared/board/zbs29v033/board.h
Normal file → Executable file
1
zbs243_shared/board/zbs29v033/board.h
Normal file → Executable file
@@ -21,6 +21,7 @@
|
||||
|
||||
#define HAS_EEPROM 1
|
||||
#define HAS_SCREEN 1
|
||||
#define AP_EMULATE_TAG 1
|
||||
|
||||
//hw types
|
||||
#define HW_TYPE SOLUM_29_033
|
||||
|
||||
1
zbs243_shared/board/zbs42v033/board.h
Normal file → Executable file
1
zbs243_shared/board/zbs42v033/board.h
Normal file → Executable file
@@ -22,6 +22,7 @@
|
||||
|
||||
#define HAS_EEPROM 1
|
||||
#define HAS_SCREEN 1
|
||||
#define AP_EMULATE_TAG 1
|
||||
|
||||
//hw types
|
||||
#define HW_TYPE SOLUM_42_033
|
||||
|
||||
1
zbs243_shared/board/zbs_nodisplay/board.h
Normal file → Executable file
1
zbs243_shared/board/zbs_nodisplay/board.h
Normal file → Executable file
@@ -8,6 +8,7 @@
|
||||
#define HAS_EEPROM 0
|
||||
#define HAS_SCREEN 0
|
||||
#define HW_TYPE SOLUM_NODISPLAY
|
||||
#define AP_EMULATE_TAG 0
|
||||
|
||||
#include "../boardCommon.h"
|
||||
|
||||
|
||||
1
zbs243_shared/board/zbs_segmented_uk/board.h
Normal file → Executable file
1
zbs243_shared/board/zbs_segmented_uk/board.h
Normal file → Executable file
@@ -7,6 +7,7 @@
|
||||
|
||||
#define HAS_EEPROM 0
|
||||
#define HAS_SCREEN 1
|
||||
#define AP_EMULATE_TAG 0
|
||||
|
||||
#define HW_TYPE SOLUM_SEG_UK
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
//nothing
|
||||
#include <stdint.h> // if we include something, we won't get a warning at compile time
|
||||
|
||||
@@ -25,7 +25,7 @@ static uint8_t flashAddrCheck(uint32_t flashAddr, uint16_t len) __reentrant /* t
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
if (pgNo)
|
||||
if (pgNo)//hmm
|
||||
return 0xff;
|
||||
pgNo = 0x80;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user