Sync work
This commit is contained in:
parent
945d2870aa
commit
efa5673e71
15 changed files with 1369 additions and 419 deletions
487
boards/MySensors.c
Normal file
487
boards/MySensors.c
Normal file
|
@ -0,0 +1,487 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "MySensors.h"
|
||||||
|
#include "nuvoton/Common.h"
|
||||||
|
#include "nuvoton/N76E003.h"
|
||||||
|
#include "nuvoton/functions.h"
|
||||||
|
#include "nuvoton/SFR_Macro.h"
|
||||||
|
|
||||||
|
#define ICSC_SYS_PACK 0x58
|
||||||
|
#define SOH 1
|
||||||
|
#define STX 2
|
||||||
|
#define ETX 3
|
||||||
|
#define EOT 4
|
||||||
|
|
||||||
|
// message buffers
|
||||||
|
MyMessage _msg; // Buffer for incoming messages
|
||||||
|
MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others)
|
||||||
|
|
||||||
|
// Receiving header information
|
||||||
|
char _header[6];
|
||||||
|
|
||||||
|
// Reception state machine control and storage variables
|
||||||
|
unsigned char _recPhase;
|
||||||
|
unsigned char _recPos;
|
||||||
|
unsigned char _recCommand;
|
||||||
|
unsigned char _recLen;
|
||||||
|
unsigned char _recStation;
|
||||||
|
unsigned char _recSender;
|
||||||
|
unsigned char _recCS;
|
||||||
|
unsigned char _recCalcCS;
|
||||||
|
unsigned char _packet_received;
|
||||||
|
unsigned char _byte;
|
||||||
|
|
||||||
|
char _data[MY_RS485_MAX_MESSAGE_LENGTH];
|
||||||
|
uint8_t _packet_len;
|
||||||
|
unsigned char _packet_from;
|
||||||
|
|
||||||
|
void delay(uint32_t u32CNT)
|
||||||
|
{
|
||||||
|
clr_T0M; //T0M=0, Timer0 Clock = Fsys/12
|
||||||
|
TMOD |= 0x01; //Timer0 is 16-bit mode
|
||||||
|
set_TR0; //Start Timer0
|
||||||
|
while (u32CNT != 0)
|
||||||
|
{
|
||||||
|
TL0 = LOBYTE(TIMER_DIV12_VALUE_1ms); //Find define in "Function_define.h" "TIMER VALUE"
|
||||||
|
TH0 = HIBYTE(TIMER_DIV12_VALUE_1ms);
|
||||||
|
while (TF0 != 1); //Check Timer0 Time-Out Flag
|
||||||
|
clr_TF0;
|
||||||
|
u32CNT --;
|
||||||
|
}
|
||||||
|
clr_TR0; //Stop Timer0
|
||||||
|
}
|
||||||
|
|
||||||
|
_Bool send(MyMessage *message, uint8_t data_type)
|
||||||
|
{
|
||||||
|
message->last = MY_NODE_ID;
|
||||||
|
message->sender = MY_NODE_ID;
|
||||||
|
message->destination = GATEWAY_ADDRESS;
|
||||||
|
message->command_echo_payload = (data_type << 5) + C_SET;
|
||||||
|
|
||||||
|
return transportSend(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Bool sendHeartbeat(void)
|
||||||
|
{
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = GATEWAY_ADDRESS;
|
||||||
|
_msgTmp.command_echo_payload = ((uint8_t) P_ULONG32 << 5) + (uint8_t) C_INTERNAL;
|
||||||
|
_msgTmp.type = I_HEARTBEAT_RESPONSE;
|
||||||
|
_msgTmp.version_length = (4 << 3) + V2_MYS_HEADER_PROTOCOL_VERSION;
|
||||||
|
_msgTmp.ulValue = 0;
|
||||||
|
|
||||||
|
return transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Bool present(const uint8_t childSensorId, const mysensors_sensor_t sensorType, char *desc)
|
||||||
|
{
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = GATEWAY_ADDRESS;
|
||||||
|
_msgTmp.command_echo_payload = (P_STRING << 5) + C_PRESENTATION;
|
||||||
|
_msgTmp.type = sensorType;
|
||||||
|
_msgTmp.sensor = childSensorId;
|
||||||
|
_msgTmp.version_length = (strlen(desc) << 3) + V2_MYS_HEADER_PROTOCOL_VERSION;
|
||||||
|
strcpy((char *)_msgTmp.data, desc);
|
||||||
|
|
||||||
|
return transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerNode(void)
|
||||||
|
{
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = GATEWAY_ADDRESS;
|
||||||
|
_msgTmp.command_echo_payload = (P_BYTE << 5) + C_INTERNAL;
|
||||||
|
_msgTmp.type = I_REGISTRATION_REQUEST;
|
||||||
|
_msgTmp.sensor = 0;
|
||||||
|
_msgTmp.version_length = (1 << 3) + V2_MYS_HEADER_PROTOCOL_VERSION;
|
||||||
|
_msgTmp.bValue = MY_CORE_VERSION;
|
||||||
|
|
||||||
|
transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendLibraryInfo(void)
|
||||||
|
{
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = GATEWAY_ADDRESS;
|
||||||
|
_msgTmp.command_echo_payload = (P_STRING << 5) + C_INTERNAL;
|
||||||
|
_msgTmp.type = I_VERSION;
|
||||||
|
_msgTmp.version_length = (strlen(MY_LIBRARY_VERSION) << 3) + V2_MYS_HEADER_PROTOCOL_VERSION;
|
||||||
|
strcpy((char *)_msgTmp.data, MY_LIBRARY_VERSION);
|
||||||
|
|
||||||
|
transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Bool sendSketchInfo(const char *name, const char *version)
|
||||||
|
{
|
||||||
|
_Bool result = 1;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = GATEWAY_ADDRESS;
|
||||||
|
_msgTmp.command_echo_payload = (P_STRING << 5) + C_INTERNAL;
|
||||||
|
_msgTmp.type = I_SKETCH_NAME;
|
||||||
|
_msgTmp.version_length = (strlen(name) << 3) + V2_MYS_HEADER_PROTOCOL_VERSION;
|
||||||
|
strcpy((char *)_msgTmp.data, name);
|
||||||
|
|
||||||
|
result &= transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
if (version) {
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = GATEWAY_ADDRESS;
|
||||||
|
_msgTmp.command_echo_payload = (P_STRING << 5) + C_INTERNAL;
|
||||||
|
_msgTmp.type = I_SKETCH_VERSION;
|
||||||
|
_msgTmp.version_length = (strlen(name) << 3) + V2_MYS_HEADER_PROTOCOL_VERSION;
|
||||||
|
strcpy((char *)_msgTmp.data, version);
|
||||||
|
|
||||||
|
result &= transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendLibraryInfo();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message delivered through _msg
|
||||||
|
_Bool _processInternalCoreMessage(void)
|
||||||
|
{
|
||||||
|
const uint8_t type = _msg.type;
|
||||||
|
if (_msg.sender == GATEWAY_ADDRESS) {
|
||||||
|
if (type == I_PRESENTATION) {
|
||||||
|
// Re-send node presentation to controller
|
||||||
|
present_node();
|
||||||
|
} else if (type == I_HEARTBEAT_REQUEST) {
|
||||||
|
(void)sendHeartbeat();
|
||||||
|
} else if (type == I_REBOOT) {
|
||||||
|
;
|
||||||
|
} else if (type == I_VERSION) {
|
||||||
|
sendLibraryInfo();
|
||||||
|
} else {
|
||||||
|
return 0; // further processing required
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0; // further processing required
|
||||||
|
}
|
||||||
|
return 1; // if not GW or no further processing required
|
||||||
|
}
|
||||||
|
|
||||||
|
void transportProcessMessage(void)
|
||||||
|
{
|
||||||
|
// get message length and limit size
|
||||||
|
const uint8_t msgLength = (_msg.version_length & 0xF8) >> 3;
|
||||||
|
// calculate expected length
|
||||||
|
|
||||||
|
const uint8_t command = _msg.command_echo_payload & 0x07;
|
||||||
|
const uint8_t type = _msg.type;
|
||||||
|
const uint8_t sender = _msg.sender;
|
||||||
|
const uint8_t destination = _msg.destination;
|
||||||
|
|
||||||
|
// Is message addressed to this node?
|
||||||
|
if (destination == MY_NODE_ID) {
|
||||||
|
// null terminate data
|
||||||
|
_msg.data[msgLength] = 0u;
|
||||||
|
// Check if sender requests an echo.
|
||||||
|
if (_msg.command_echo_payload & 0x08) {
|
||||||
|
memcpy(&_msgTmp, &_msg, sizeof(_msg)); // Copy message
|
||||||
|
// Reply without echo flag (otherwise we would end up in an eternal loop)
|
||||||
|
_msgTmp.command_echo_payload = _msgTmp.command_echo_payload & 0xE7;
|
||||||
|
_msgTmp.command_echo_payload = _msgTmp.command_echo_payload | 0x10;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = sender;
|
||||||
|
transportSend(&_msgTmp);
|
||||||
|
}
|
||||||
|
if(!(_msg.command_echo_payload & 0x10)) {
|
||||||
|
// only process if not ECHO
|
||||||
|
if (command == C_INTERNAL) {
|
||||||
|
if (type == I_ID_RESPONSE) {
|
||||||
|
return; // no further processing required
|
||||||
|
}
|
||||||
|
// general
|
||||||
|
if (type == I_PING) {
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = sender;
|
||||||
|
_msgTmp.command_echo_payload = (P_BYTE << 5) + C_INTERNAL;
|
||||||
|
_msgTmp.type = I_PONG;
|
||||||
|
_msgTmp.bValue = 1;
|
||||||
|
transportSend(&_msgTmp);
|
||||||
|
return; // no further processing required
|
||||||
|
}
|
||||||
|
if (type == I_PONG) {
|
||||||
|
return; // no further processing required
|
||||||
|
}
|
||||||
|
if (_processInternalCoreMessage()) {
|
||||||
|
return; // no further processing required
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Call incoming message callback if available
|
||||||
|
receive(&_msg);
|
||||||
|
} else if (destination == BROADCAST_ADDRESS) {
|
||||||
|
if (command == C_INTERNAL) {
|
||||||
|
if (type == I_DISCOVER_REQUEST) {
|
||||||
|
|
||||||
|
delay(MY_NODE_ID * 50);
|
||||||
|
|
||||||
|
_msgTmp.last = MY_NODE_ID;
|
||||||
|
_msgTmp.sender = MY_NODE_ID;
|
||||||
|
_msgTmp.destination = sender;
|
||||||
|
_msgTmp.command_echo_payload = (P_BYTE << 5) + C_INTERNAL;
|
||||||
|
_msgTmp.type = I_DISCOVER_RESPONSE;
|
||||||
|
_msgTmp.bValue = GATEWAY_ADDRESS;
|
||||||
|
transportSend(&_msgTmp);
|
||||||
|
return; // no further processing required
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (command != C_INTERNAL) {
|
||||||
|
receive(&_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reset the state machine and release the data pointer
|
||||||
|
void _serialReset()
|
||||||
|
{
|
||||||
|
_recPhase = 0;
|
||||||
|
_recPos = 0;
|
||||||
|
_recLen = 0;
|
||||||
|
_recCommand = 0;
|
||||||
|
_recCS = 0;
|
||||||
|
_recCalcCS = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the main reception state machine. Progress through the states
|
||||||
|
// is keyed on either special control characters, or counted number of bytes
|
||||||
|
// received. If all the data is in the right format, and the calculated
|
||||||
|
// checksum matches the received checksum, AND the destination station is
|
||||||
|
// our station ID, then look for a registered command that matches the
|
||||||
|
// command code. If all the above is true, execute the command's
|
||||||
|
// function.
|
||||||
|
_Bool _serialProcess()
|
||||||
|
{
|
||||||
|
unsigned char i;
|
||||||
|
if (!RI) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_byte = SBUF;
|
||||||
|
RI = 0;
|
||||||
|
|
||||||
|
switch(_recPhase) {
|
||||||
|
|
||||||
|
// Case 0 looks for the header. Bytes arrive in the serial interface and get
|
||||||
|
// shifted through a header buffer. When the start and end characters in
|
||||||
|
// the buffer match the SOH/STX pair, and the destination station ID matches
|
||||||
|
// our ID, save the header information and progress to the next state.
|
||||||
|
case 0:
|
||||||
|
memcpy(&_header[0],&_header[1],5);
|
||||||
|
_header[5] = _byte;
|
||||||
|
|
||||||
|
if ((_header[0] == SOH) && (_header[5] == STX) && (_header[1] != _header[2])) {
|
||||||
|
_recCalcCS = 0;
|
||||||
|
_recStation = _header[1];
|
||||||
|
_recSender = _header[2];
|
||||||
|
_recCommand = _header[3];
|
||||||
|
_recLen = _header[4];
|
||||||
|
|
||||||
|
for (i=1; i<=4; i++) {
|
||||||
|
_recCalcCS += _header[i];
|
||||||
|
}
|
||||||
|
_recPhase = 1;
|
||||||
|
_recPos = 0;
|
||||||
|
|
||||||
|
//Avoid _data[] overflow
|
||||||
|
if (_recLen >= MY_RS485_MAX_MESSAGE_LENGTH) {
|
||||||
|
_serialReset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if we should process this message
|
||||||
|
//We reject the message if we are the sender
|
||||||
|
//We reject if we are not the receiver and message is not a broadcast
|
||||||
|
if ((_recSender == MY_NODE_ID) ||
|
||||||
|
(_recStation != MY_NODE_ID &&
|
||||||
|
_recStation != BROADCAST_ADDRESS)) {
|
||||||
|
_serialReset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recLen == 0) {
|
||||||
|
_recPhase = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Case 1 receives the data portion of the packet. Read in "_recLen" number
|
||||||
|
// of bytes and store them in the _data array.
|
||||||
|
case 1:
|
||||||
|
_data[_recPos++] = _byte;
|
||||||
|
_recCalcCS += _byte;
|
||||||
|
if (_recPos == _recLen) {
|
||||||
|
_recPhase = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// After the data comes a single ETX character. Do we have it? If not,
|
||||||
|
// reset the state machine to default and start looking for a new header.
|
||||||
|
case 2:
|
||||||
|
// Packet properly terminated?
|
||||||
|
if (_byte == ETX) {
|
||||||
|
_recPhase = 3;
|
||||||
|
} else {
|
||||||
|
_serialReset();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Next comes the checksum. We have already calculated it from the incoming
|
||||||
|
// data, so just store the incoming checksum byte for later.
|
||||||
|
case 3:
|
||||||
|
_recCS = _byte;
|
||||||
|
_recPhase = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// The final state - check the last character is EOT and that the checksum matches.
|
||||||
|
// If that test passes, then look for a valid command callback to execute.
|
||||||
|
// Execute it if found.
|
||||||
|
case 4:
|
||||||
|
if (_byte == EOT) {
|
||||||
|
if (_recCS == _recCalcCS) {
|
||||||
|
// First, check for system level commands. It is possible
|
||||||
|
// to register your own callback as well for system level
|
||||||
|
// commands which will be called after the system default
|
||||||
|
// hook.
|
||||||
|
|
||||||
|
switch (_recCommand) {
|
||||||
|
case ICSC_SYS_PACK:
|
||||||
|
_packet_from = _recSender;
|
||||||
|
_packet_len = _recLen;
|
||||||
|
_packet_received = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Clear the data
|
||||||
|
_serialReset();
|
||||||
|
//Return true, we have processed one command
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Bool transportSend(MyMessage* data)
|
||||||
|
{
|
||||||
|
const char *datap = (const char *)data;
|
||||||
|
unsigned char i;
|
||||||
|
unsigned char len;
|
||||||
|
unsigned char cs = 0;
|
||||||
|
|
||||||
|
// This is how many times to try and transmit before failing.
|
||||||
|
unsigned char timeout = 10;
|
||||||
|
|
||||||
|
// Let's start out by looking for a collision. If there has been anything seen in
|
||||||
|
// the last millisecond, then wait for a random time and check again.
|
||||||
|
|
||||||
|
while (_serialProcess()) {
|
||||||
|
unsigned char del;
|
||||||
|
del = rand() % 20;
|
||||||
|
for (i = 0; i < del; i++) {
|
||||||
|
delay(1);
|
||||||
|
_serialProcess();
|
||||||
|
}
|
||||||
|
timeout--;
|
||||||
|
if (timeout == 0) {
|
||||||
|
// Failed to transmit!!!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rs485_out();
|
||||||
|
|
||||||
|
// Start of header by writing multiple SOH
|
||||||
|
for(uint8_t w=0; w<MY_RS485_SOH_COUNT; w++) {
|
||||||
|
TI = 0;
|
||||||
|
SBUF = SOH;
|
||||||
|
while (TI == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = data->destination;
|
||||||
|
while (TI == 0);
|
||||||
|
cs += data->destination;
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = MY_NODE_ID;
|
||||||
|
while (TI == 0);
|
||||||
|
cs += MY_NODE_ID;
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = ICSC_SYS_PACK;
|
||||||
|
while (TI == 0);
|
||||||
|
cs += ICSC_SYS_PACK;
|
||||||
|
|
||||||
|
len = (data->version_length >> 3) + V2_MYS_HEADER_SIZE;
|
||||||
|
TI = 0;
|
||||||
|
SBUF = len;
|
||||||
|
while (TI == 0);
|
||||||
|
cs += len;
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = STX;
|
||||||
|
while (TI == 0);
|
||||||
|
|
||||||
|
for(i=0; i<len; i++) {
|
||||||
|
TI = 0;
|
||||||
|
SBUF = datap[i];
|
||||||
|
while(TI == 0);
|
||||||
|
cs += datap[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = ETX;
|
||||||
|
while (TI == 0);
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = cs;
|
||||||
|
while (TI == 0);
|
||||||
|
|
||||||
|
TI = 0;
|
||||||
|
SBUF = EOT;
|
||||||
|
while (TI == 0);
|
||||||
|
|
||||||
|
rs485_in();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transportInitialise(void)
|
||||||
|
{
|
||||||
|
rs485_in();
|
||||||
|
_serialReset();
|
||||||
|
RI = 0;
|
||||||
|
srand(MY_NODE_ID);
|
||||||
|
delay(MY_NODE_ID * 50);
|
||||||
|
present_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
void transportProcess(void)
|
||||||
|
{
|
||||||
|
_serialProcess();
|
||||||
|
if (transportReceive(&_msg))
|
||||||
|
transportProcessMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t transportReceive(void* data)
|
||||||
|
{
|
||||||
|
if (_packet_received) {
|
||||||
|
memcpy(data,_data,_packet_len);
|
||||||
|
_packet_received = 0;
|
||||||
|
return _packet_len;
|
||||||
|
} else {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
320
boards/MySensors.h
Normal file
320
boards/MySensors.h
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
#ifndef MySensors_h
|
||||||
|
#define MySensors_h
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void rs485_in(void);
|
||||||
|
void rs485_out(void);
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned int uint16_t;
|
||||||
|
typedef unsigned long uint32_t;
|
||||||
|
typedef signed int int16_t;
|
||||||
|
typedef signed long int32_t;
|
||||||
|
|
||||||
|
#define MY_LIBRARY_VERSION "NUVO 1.0"
|
||||||
|
|
||||||
|
#define GATEWAY_ADDRESS ((uint8_t)0) //!< Node ID for GW sketch
|
||||||
|
//#define MY_NODE_ID ((uint8_t)201)
|
||||||
|
#define NODE_SENSOR_ID ((uint8_t)255) //!< Node child is always created/presented when a node is started
|
||||||
|
#define MY_CORE_VERSION ((uint8_t)2) //!< core version
|
||||||
|
#define MY_CORE_MIN_VERSION ((uint8_t)2) //!< min core version required for compatibility
|
||||||
|
|
||||||
|
#define V2_MYS_HEADER_PROTOCOL_VERSION (2u) //!< Protocol version
|
||||||
|
#define V2_MYS_HEADER_SIZE (7u) //!< Header size
|
||||||
|
#define V2_MYS_HEADER_MAX_MESSAGE_SIZE (32u) //!< Max payload size
|
||||||
|
|
||||||
|
#define V2_MYS_HEADER_VSL_VERSION_POS (0) //!< bitfield position version
|
||||||
|
#define V2_MYS_HEADER_VSL_VERSION_SIZE (2u) //!< size version field
|
||||||
|
#define V2_MYS_HEADER_VSL_SIGNED_POS (2u) //!< bitfield position signed field
|
||||||
|
#define V2_MYS_HEADER_VSL_SIGNED_SIZE (1u) //!< size signed field
|
||||||
|
#define V2_MYS_HEADER_VSL_LENGTH_POS (3u) //!< bitfield position length field
|
||||||
|
#define V2_MYS_HEADER_VSL_LENGTH_SIZE (5u) //!< size length field
|
||||||
|
|
||||||
|
#define V2_MYS_HEADER_CEP_COMMAND_POS (0) //!< bitfield position command field
|
||||||
|
#define V2_MYS_HEADER_CEP_COMMAND_SIZE (3u) //!< size command field
|
||||||
|
#define V2_MYS_HEADER_CEP_ECHOREQUEST_POS (3u) //!< bitfield position echo request field
|
||||||
|
#define V2_MYS_HEADER_CEP_ECHOREQUEST_SIZE (1u) //!< size echo request field
|
||||||
|
#define V2_MYS_HEADER_CEP_ECHO_POS (4u) //!< bitfield position echo field
|
||||||
|
#define V2_MYS_HEADER_CEP_ECHO_SIZE (1u) //!< size echo field
|
||||||
|
#define V2_MYS_HEADER_CEP_PAYLOADTYPE_POS (5u) //!< bitfield position payload type field
|
||||||
|
#define V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE (3u) //!< size payload type field
|
||||||
|
|
||||||
|
#define MAX_MESSAGE_SIZE V2_MYS_HEADER_MAX_MESSAGE_SIZE //!< The maximum size of a message (including header)
|
||||||
|
#define HEADER_SIZE V2_MYS_HEADER_SIZE //!< The size of the header
|
||||||
|
#define MAX_PAYLOAD_SIZE (MAX_MESSAGE_SIZE - HEADER_SIZE) //!< The maximum size of a payload depends on #MAX_MESSAGE_SIZE and #HEADER_SIZE
|
||||||
|
#define MY_RS485_MAX_MESSAGE_LENGTH MAX_MESSAGE_SIZE
|
||||||
|
#define MY_RS485_SOH_COUNT 1
|
||||||
|
|
||||||
|
#define MY_CAP_RESET "N"
|
||||||
|
#define MY_CAP_OTA_FW "N"
|
||||||
|
#define MY_CAP_RADIO "S"
|
||||||
|
#define MY_CAP_TYPE "N"
|
||||||
|
#define MY_CAP_ARCH "F"
|
||||||
|
#define MY_CAP_SIGN "-"
|
||||||
|
#define MY_CAP_RXBUF "-"
|
||||||
|
#define MY_CAP_ENCR "-"
|
||||||
|
#define MY_CAPABILITIES MY_CAP_RESET MY_CAP_RADIO MY_CAP_OTA_FW MY_CAP_TYPE MY_CAP_ARCH MY_CAP_SIGN MY_CAP_RXBUF MY_CAP_ENCR
|
||||||
|
|
||||||
|
#define MY_TRANSPORT_MAX_TX_FAILURES (10u) //!< search for a new parent node after this many transmission failures, higher threshold for repeating nodes
|
||||||
|
#define MY_TRANSPORT_MAX_TSM_FAILURES (7u) //!< Max. number of consecutive TSM failure state entries (3bits)
|
||||||
|
#define MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE_MS (60*1000ul) //!< Duration extended failure state (in ms)
|
||||||
|
#define MY_TRANSPORT_STATE_TIMEOUT_MS (2*1000ul) //!< general state timeout (in ms)
|
||||||
|
#define MY_TRANSPORT_CHKUPL_INTERVAL_MS (10*1000ul) //!< Interval to re-check uplink (in ms)
|
||||||
|
#define MY_TRANSPORT_STATE_RETRIES (3u) //!< retries before switching to FAILURE
|
||||||
|
|
||||||
|
#define BROADCAST_ADDRESS (255u) //!< broadcasts are addressed to ID 255
|
||||||
|
#define MAX_SUBSEQ_MSGS (5u) //!< Maximum number of subsequently processed messages in FIFO (to prevent transport deadlock if HW issue)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Node core configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// @brief The command field (message-type) defines the overall properties of a message
|
||||||
|
typedef enum {
|
||||||
|
C_PRESENTATION = 0, //!< Sent by a node when they present attached sensors. This is usually done in presentation() at startup.
|
||||||
|
C_SET = 1, //!< This message is sent from or to a sensor when a sensor value should be updated.
|
||||||
|
C_REQ = 2, //!< Requests a variable value (usually from an actuator destined for controller).
|
||||||
|
C_INTERNAL = 3, //!< Internal MySensors messages (also include common messages provided/generated by the library).
|
||||||
|
C_STREAM = 4, //!< For firmware and other larger chunks of data that need to be divided into pieces.
|
||||||
|
C_RESERVED_5 = 5, //!< C_RESERVED_5
|
||||||
|
C_RESERVED_6 = 6, //!< C_RESERVED_6
|
||||||
|
C_INVALID_7 = 7 //!< C_INVALID_7
|
||||||
|
} mysensors_command_t;
|
||||||
|
|
||||||
|
/// @brief Type of sensor (used when presenting sensors)
|
||||||
|
typedef enum {
|
||||||
|
S_DOOR = 0, //!< Door sensor, V_TRIPPED, V_ARMED
|
||||||
|
S_MOTION = 1, //!< Motion sensor, V_TRIPPED, V_ARMED
|
||||||
|
S_SMOKE = 2, //!< Smoke sensor, V_TRIPPED, V_ARMED
|
||||||
|
S_BINARY = 3, //!< Binary light or relay, V_STATUS, V_WATT
|
||||||
|
S_LIGHT = 3, //!< \deprecated Same as S_BINARY
|
||||||
|
S_DIMMER = 4, //!< Dimmable light or fan device, V_STATUS (on/off), V_PERCENTAGE (dimmer level 0-100), V_WATT
|
||||||
|
S_COVER = 5, //!< Blinds or window cover, V_UP, V_DOWN, V_STOP, V_PERCENTAGE (open/close to a percentage)
|
||||||
|
S_TEMP = 6, //!< Temperature sensor, V_TEMP
|
||||||
|
S_HUM = 7, //!< Humidity sensor, V_HUM
|
||||||
|
S_BARO = 8, //!< Barometer sensor, V_PRESSURE, V_FORECAST
|
||||||
|
S_WIND = 9, //!< Wind sensor, V_WIND, V_GUST
|
||||||
|
S_RAIN = 10, //!< Rain sensor, V_RAIN, V_RAINRATE
|
||||||
|
S_UV = 11, //!< Uv sensor, V_UV
|
||||||
|
S_WEIGHT = 12, //!< Personal scale sensor, V_WEIGHT, V_IMPEDANCE
|
||||||
|
S_POWER = 13, //!< Power meter, V_WATT, V_KWH, V_VAR, V_VA, V_POWER_FACTOR
|
||||||
|
S_HEATER = 14, //!< Header device, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_STATE, V_TEMP
|
||||||
|
S_DISTANCE = 15, //!< Distance sensor, V_DISTANCE
|
||||||
|
S_LIGHT_LEVEL = 16, //!< Light level sensor, V_LIGHT_LEVEL (uncalibrated in percentage), V_LEVEL (light level in lux)
|
||||||
|
S_ARDUINO_NODE = 17, //!< Used (internally) for presenting a non-repeating Arduino node
|
||||||
|
S_ARDUINO_REPEATER_NODE = 18, //!< Used (internally) for presenting a repeating Arduino node
|
||||||
|
S_LOCK = 19, //!< Lock device, V_LOCK_STATUS
|
||||||
|
S_IR = 20, //!< IR device, V_IR_SEND, V_IR_RECEIVE
|
||||||
|
S_WATER = 21, //!< Water meter, V_FLOW, V_VOLUME
|
||||||
|
S_AIR_QUALITY = 22, //!< Air quality sensor, V_LEVEL
|
||||||
|
S_CUSTOM = 23, //!< Custom sensor
|
||||||
|
S_DUST = 24, //!< Dust sensor, V_LEVEL
|
||||||
|
S_SCENE_CONTROLLER = 25, //!< Scene controller device, V_SCENE_ON, V_SCENE_OFF.
|
||||||
|
S_RGB_LIGHT = 26, //!< RGB light. Send color component data using V_RGB. Also supports V_WATT
|
||||||
|
S_RGBW_LIGHT = 27, //!< RGB light with an additional White component. Send data using V_RGBW. Also supports V_WATT
|
||||||
|
S_COLOR_SENSOR = 28, //!< Color sensor, send color information using V_RGB
|
||||||
|
S_HVAC = 29, //!< Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_TEMP
|
||||||
|
S_MULTIMETER = 30, //!< Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE
|
||||||
|
S_SPRINKLER = 31, //!< Sprinkler, V_STATUS (turn on/off), V_TRIPPED (if fire detecting device)
|
||||||
|
S_WATER_LEAK = 32, //!< Water leak sensor, V_TRIPPED, V_ARMED
|
||||||
|
S_SOUND = 33, //!< Sound sensor, V_TRIPPED, V_ARMED, V_LEVEL (sound level in dB)
|
||||||
|
S_VIBRATION = 34, //!< Vibration sensor, V_TRIPPED, V_ARMED, V_LEVEL (vibration in Hz)
|
||||||
|
S_MOISTURE = 35, //!< Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?)
|
||||||
|
S_INFO = 36, //!< LCD text device / Simple information device on controller, V_TEXT
|
||||||
|
S_GAS = 37, //!< Gas meter, V_FLOW, V_VOLUME
|
||||||
|
S_GPS = 38, //!< GPS Sensor, V_POSITION
|
||||||
|
S_WATER_QUALITY = 39 //!< V_TEMP, V_PH, V_ORP, V_EC, V_STATUS
|
||||||
|
} mysensors_sensor_t;
|
||||||
|
|
||||||
|
/// @brief Type of sensor data (for set/req/echo messages)
|
||||||
|
typedef enum {
|
||||||
|
V_TEMP = 0, //!< S_TEMP. Temperature S_TEMP, S_HEATER, S_HVAC
|
||||||
|
V_HUM = 1, //!< S_HUM. Humidity
|
||||||
|
V_STATUS = 2, //!< S_BINARY, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting/reporting binary (on/off) status. 1=on, 0=off
|
||||||
|
V_LIGHT = 2, //!< \deprecated Same as V_STATUS
|
||||||
|
V_PERCENTAGE = 3, //!< S_DIMMER. Used for sending a percentage value 0-100 (%).
|
||||||
|
V_DIMMER = 3, //!< \deprecated Same as V_PERCENTAGE
|
||||||
|
V_PRESSURE = 4, //!< S_BARO. Atmospheric Pressure
|
||||||
|
V_FORECAST = 5, //!< S_BARO. Whether forecast. string of "stable", "sunny", "cloudy", "unstable", "thunderstorm" or "unknown"
|
||||||
|
V_RAIN = 6, //!< S_RAIN. Amount of rain
|
||||||
|
V_RAINRATE = 7, //!< S_RAIN. Rate of rain
|
||||||
|
V_WIND = 8, //!< S_WIND. Wind speed
|
||||||
|
V_GUST = 9, //!< S_WIND. Gust
|
||||||
|
V_DIRECTION = 10, //!< S_WIND. Wind direction 0-360 (degrees)
|
||||||
|
V_UV = 11, //!< S_UV. UV light level
|
||||||
|
V_WEIGHT = 12, //!< S_WEIGHT. Weight(for scales etc)
|
||||||
|
V_DISTANCE = 13, //!< S_DISTANCE. Distance
|
||||||
|
V_IMPEDANCE = 14, //!< S_MULTIMETER, S_WEIGHT. Impedance value
|
||||||
|
V_ARMED = 15, //!< S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER. Armed status of a security sensor. 1 = Armed, 0 = Bypassed
|
||||||
|
V_TRIPPED = 16, //!< S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER, S_WATER_LEAK, S_SOUND, S_VIBRATION, S_MOISTURE. Tripped status of a security sensor. 1 = Tripped, 0
|
||||||
|
V_WATT = 17, //!< S_POWER, S_BINARY, S_DIMMER, S_RGB_LIGHT, S_RGBW_LIGHT. Watt value for power meters
|
||||||
|
V_KWH = 18, //!< S_POWER. Accumulated number of KWH for a power meter
|
||||||
|
V_SCENE_ON = 19, //!< S_SCENE_CONTROLLER. Turn on a scene
|
||||||
|
V_SCENE_OFF = 20, //!< S_SCENE_CONTROLLER. Turn of a scene
|
||||||
|
V_HVAC_FLOW_STATE = 21, //!< S_HEATER, S_HVAC. HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver")
|
||||||
|
V_HEATER = 21, //!< \deprecated Same as V_HVAC_FLOW_STATE
|
||||||
|
V_HVAC_SPEED = 22, //!< S_HVAC, S_HEATER. HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto")
|
||||||
|
V_LIGHT_LEVEL = 23, //!< S_LIGHT_LEVEL. Uncalibrated light level. 0-100%. Use V_LEVEL for light level in lux
|
||||||
|
V_VAR1 = 24, //!< VAR1
|
||||||
|
V_VAR2 = 25, //!< VAR2
|
||||||
|
V_VAR3 = 26, //!< VAR3
|
||||||
|
V_VAR4 = 27, //!< VAR4
|
||||||
|
V_VAR5 = 28, //!< VAR5
|
||||||
|
V_UP = 29, //!< S_COVER. Window covering. Up
|
||||||
|
V_DOWN = 30, //!< S_COVER. Window covering. Down
|
||||||
|
V_STOP = 31, //!< S_COVER. Window covering. Stop
|
||||||
|
V_IR_SEND = 32, //!< S_IR. Send out an IR-command
|
||||||
|
V_IR_RECEIVE = 33, //!< S_IR. This message contains a received IR-command
|
||||||
|
V_FLOW = 34, //!< S_WATER. Flow of water (in meter)
|
||||||
|
V_VOLUME = 35, //!< S_WATER. Water volume
|
||||||
|
V_LOCK_STATUS = 36, //!< S_LOCK. Set or get lock status. 1=Locked, 0=Unlocked
|
||||||
|
V_LEVEL = 37, //!< S_DUST, S_AIR_QUALITY, S_SOUND (dB), S_VIBRATION (hz), S_LIGHT_LEVEL (lux)
|
||||||
|
V_VOLTAGE = 38, //!< S_MULTIMETER
|
||||||
|
V_CURRENT = 39, //!< S_MULTIMETER
|
||||||
|
V_RGB = 40, //!< S_RGB_LIGHT, S_COLOR_SENSOR. Sent as ASCII hex: RRGGBB (RR=red, GG=green, BB=blue component)
|
||||||
|
V_RGBW = 41, //!< S_RGBW_LIGHT. Sent as ASCII hex: RRGGBBWW (WW=white component)
|
||||||
|
V_ID = 42, //!< Used for sending in sensors hardware ids (i.e. OneWire DS1820b).
|
||||||
|
V_UNIT_PREFIX = 43, //!< Allows sensors to send in a string representing the unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch.
|
||||||
|
V_HVAC_SETPOINT_COOL = 44, //!< S_HVAC. HVAC cool setpoint (Integer between 0-100)
|
||||||
|
V_HVAC_SETPOINT_HEAT = 45, //!< S_HEATER, S_HVAC. HVAC/Heater setpoint (Integer between 0-100)
|
||||||
|
V_HVAC_FLOW_MODE = 46, //!< S_HVAC. Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn")
|
||||||
|
V_TEXT = 47, //!< S_INFO. Text message to display on LCD or controller device
|
||||||
|
V_CUSTOM = 48, //!< Custom messages used for controller/inter node specific commands, preferably using S_CUSTOM device type.
|
||||||
|
V_POSITION = 49, //!< GPS position and altitude. Payload: latitude;longitude;altitude(m). E.g. "55.722526;13.017972;18"
|
||||||
|
V_IR_RECORD = 50, //!< Record IR codes S_IR for playback
|
||||||
|
V_PH = 51, //!< S_WATER_QUALITY, water PH
|
||||||
|
V_ORP = 52, //!< S_WATER_QUALITY, water ORP : redox potential in mV
|
||||||
|
V_EC = 53, //!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm)
|
||||||
|
V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var)
|
||||||
|
V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA)
|
||||||
|
V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1]
|
||||||
|
} mysensors_data_t;
|
||||||
|
|
||||||
|
/// @brief Type of internal messages (for internal messages)
|
||||||
|
typedef enum {
|
||||||
|
I_BATTERY_LEVEL = 0, //!< Battery level
|
||||||
|
I_TIME = 1, //!< Time (request/response)
|
||||||
|
I_VERSION = 2, //!< Version
|
||||||
|
I_ID_REQUEST = 3, //!< ID request
|
||||||
|
I_ID_RESPONSE = 4, //!< ID response
|
||||||
|
I_INCLUSION_MODE = 5, //!< Inclusion mode
|
||||||
|
I_CONFIG = 6, //!< Config (request/response)
|
||||||
|
I_FIND_PARENT_REQUEST = 7, //!< Find parent
|
||||||
|
I_FIND_PARENT_RESPONSE = 8, //!< Find parent response
|
||||||
|
I_LOG_MESSAGE = 9, //!< Log message
|
||||||
|
I_CHILDREN = 10, //!< Children
|
||||||
|
I_SKETCH_NAME = 11, //!< Sketch name
|
||||||
|
I_SKETCH_VERSION = 12, //!< Sketch version
|
||||||
|
I_REBOOT = 13, //!< Reboot request
|
||||||
|
I_GATEWAY_READY = 14, //!< Gateway ready
|
||||||
|
I_SIGNING_PRESENTATION = 15, //!< Provides signing related preferences (first byte is preference version)
|
||||||
|
I_NONCE_REQUEST = 16, //!< Request for a nonce
|
||||||
|
I_NONCE_RESPONSE = 17, //!< Payload is nonce data
|
||||||
|
I_HEARTBEAT_REQUEST = 18, //!< Heartbeat request
|
||||||
|
I_PRESENTATION = 19, //!< Presentation message
|
||||||
|
I_DISCOVER_REQUEST = 20, //!< Discover request
|
||||||
|
I_DISCOVER_RESPONSE = 21, //!< Discover response
|
||||||
|
I_HEARTBEAT_RESPONSE = 22, //!< Heartbeat response
|
||||||
|
I_LOCKED = 23, //!< Node is locked (reason in string-payload)
|
||||||
|
I_PING = 24, //!< Ping sent to node, payload incremental hop counter
|
||||||
|
I_PONG = 25, //!< In return to ping, sent back to sender, payload incremental hop counter
|
||||||
|
I_REGISTRATION_REQUEST = 26, //!< Register request to GW
|
||||||
|
I_REGISTRATION_RESPONSE = 27, //!< Register response from GW
|
||||||
|
I_DEBUG = 28, //!< Debug message
|
||||||
|
I_SIGNAL_REPORT_REQUEST = 29, //!< Device signal strength request
|
||||||
|
I_SIGNAL_REPORT_REVERSE = 30, //!< Internal
|
||||||
|
I_SIGNAL_REPORT_RESPONSE = 31, //!< Device signal strength response (RSSI)
|
||||||
|
I_PRE_SLEEP_NOTIFICATION = 32, //!< Message sent before node is going to sleep
|
||||||
|
I_POST_SLEEP_NOTIFICATION = 33 //!< Message sent after node woke up (if enabled)
|
||||||
|
} mysensors_internal_t;
|
||||||
|
|
||||||
|
/// @brief Type of data stream (for streamed message)
|
||||||
|
typedef enum {
|
||||||
|
ST_FIRMWARE_CONFIG_REQUEST = 0, //!< Request new FW, payload contains current FW details
|
||||||
|
ST_FIRMWARE_CONFIG_RESPONSE = 1, //!< New FW details to initiate OTA FW update
|
||||||
|
ST_FIRMWARE_REQUEST = 2, //!< Request FW block
|
||||||
|
ST_FIRMWARE_RESPONSE = 3, //!< Response FW block
|
||||||
|
ST_SOUND = 4, //!< Sound
|
||||||
|
ST_IMAGE = 5, //!< Image
|
||||||
|
ST_FIRMWARE_CONFIRM = 6, //!< Mark running firmware as valid (MyOTAFirmwareUpdateNVM + mcuboot)
|
||||||
|
ST_FIRMWARE_RESPONSE_RLE = 7, //!< Response FW block with run length encoded data
|
||||||
|
} mysensors_stream_t;
|
||||||
|
|
||||||
|
/// @brief Type of payload
|
||||||
|
typedef enum {
|
||||||
|
P_STRING = 0, //!< Payload type is string
|
||||||
|
P_BYTE = 1, //!< Payload type is byte
|
||||||
|
P_INT16 = 2, //!< Payload type is INT16
|
||||||
|
P_UINT16 = 3, //!< Payload type is UINT16
|
||||||
|
P_LONG32 = 4, //!< Payload type is INT32
|
||||||
|
P_ULONG32 = 5, //!< Payload type is UINT32
|
||||||
|
P_CUSTOM = 6, //!< Payload type is binary
|
||||||
|
P_FLOAT32 = 7 //!< Payload type is float32
|
||||||
|
} mysensors_payload_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
|
||||||
|
uint8_t last; //!< 8 bit - Id of last node this message passed
|
||||||
|
uint8_t sender; //!< 8 bit - Id of sender node (origin)
|
||||||
|
uint8_t destination; //!< 8 bit - Id of destination node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 bit - Protocol version<br>
|
||||||
|
* 1 bit - Signed flag<br>
|
||||||
|
* 5 bit - Length of payload
|
||||||
|
*/
|
||||||
|
uint8_t version_length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3 bit - Command type<br>
|
||||||
|
* 1 bit - Request an echo - Indicator that receiver should echo the message back to the sender<br>
|
||||||
|
* 1 bit - Is echo message - Indicator that this is the echoed message<br>
|
||||||
|
* 3 bit - Payload data type
|
||||||
|
*/
|
||||||
|
uint8_t command_echo_payload;
|
||||||
|
|
||||||
|
uint8_t type; //!< 8 bit - Type varies depending on command
|
||||||
|
uint8_t sensor; //!< 8 bit - Id of sensor that this message concerns.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each message can transfer a payload. We add one extra byte for string
|
||||||
|
* terminator \0 to be "printable" this is not transferred OTA
|
||||||
|
* This union is used to simplify the construction of the binary data types transferred.
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
uint8_t bValue; //!< unsigned byte value (8-bit)
|
||||||
|
uint16_t uiValue; //!< unsigned integer value (16-bit)
|
||||||
|
int16_t iValue; //!< signed integer value (16-bit)
|
||||||
|
uint32_t ulValue; //!< unsigned long value (32-bit)
|
||||||
|
int32_t lValue; //!< signed long value (32-bit)
|
||||||
|
struct { //!< Float messages
|
||||||
|
float fValue;
|
||||||
|
uint8_t fPrecision; //!< Number of decimals when serializing
|
||||||
|
};
|
||||||
|
char data[MAX_PAYLOAD_SIZE + 1]; //!< Buffer for raw payload data
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uint8_t array[HEADER_SIZE + MAX_PAYLOAD_SIZE + 1]; //!< buffer for entire message
|
||||||
|
} MyMessage;
|
||||||
|
|
||||||
|
void delay(uint32_t i);
|
||||||
|
void registerNode(void);
|
||||||
|
void present_node(void);
|
||||||
|
_Bool present(const uint8_t sensorId, const mysensors_sensor_t sensorType, char *desc);
|
||||||
|
_Bool sendSketchInfo(const char *name, const char *version);
|
||||||
|
_Bool send(MyMessage *msg,uint8_t data_type);
|
||||||
|
_Bool sendHeartbeat(void);
|
||||||
|
void receive(const MyMessage*);
|
||||||
|
void transportProcessMessage(void);
|
||||||
|
_Bool transportSend(MyMessage *message);
|
||||||
|
void transportInitialise(void);
|
||||||
|
void transportProcess(void);
|
||||||
|
uint8_t transportReceive(void *data);
|
||||||
|
_Bool isMessageReceived(void);
|
||||||
|
void resetMessageReceived(void);
|
||||||
|
uint32_t transportGetHeartbeat(void);
|
||||||
|
|
||||||
|
#endif // MySensors_h
|
5
boards/build.sh
Executable file
5
boards/build.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
sdcc -mmcs51 -o lc.ihx lc.c -D FOSC_160000 -I../include
|
||||||
|
sdcc -mmcs51 --model-large -c MySensors.c -D FOSC_160000 -D MY_NODE_ID=201 -I../include
|
||||||
|
sdcc -mmcs51 --model-large -o chan8.ihx chan8.c MySensors.rel -D FOSC_160000 -I../include
|
||||||
|
sdcc -mmcs51 --model-large -c MySensors.c -D FOSC_160000 -D MY_NODE_ID=202 -I../include
|
||||||
|
sdcc -mmcs51 --model-large -o rs485relay.ihx rs485relay.c MySensors.rel -D FOSC_160000 -I../include
|
167
boards/chan8.c
Normal file
167
boards/chan8.c
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
#include <nuvoton/functions.h>
|
||||||
|
#include <nuvoton/N76E003.h>
|
||||||
|
#include <nuvoton/Common.h>
|
||||||
|
#include <nuvoton/SFR_Macro.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MySensors.h"
|
||||||
|
|
||||||
|
#define M0 P03
|
||||||
|
#define M1 P04
|
||||||
|
#define M2 P01
|
||||||
|
|
||||||
|
#define RS485_DIR P05
|
||||||
|
|
||||||
|
#define OE P13
|
||||||
|
#define DS P14
|
||||||
|
#define SHCP P11
|
||||||
|
#define STCP P12
|
||||||
|
|
||||||
|
#define MAXCMD 64
|
||||||
|
|
||||||
|
unsigned char relay;
|
||||||
|
|
||||||
|
unsigned char crc;
|
||||||
|
|
||||||
|
void rs485_in(void) {
|
||||||
|
RS485_DIR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rs485_out(void) {
|
||||||
|
RS485_DIR = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(void) {
|
||||||
|
OE = 0;
|
||||||
|
STCP = 0;
|
||||||
|
SHCP = 0;
|
||||||
|
|
||||||
|
DS = (relay & 0x01)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x02)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x04)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x08)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x10)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x20)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x40)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x80)? 1 : 0;
|
||||||
|
|
||||||
|
SHCP = 1;
|
||||||
|
STCP = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void receive(const MyMessage* mymsg)
|
||||||
|
{
|
||||||
|
uint8_t sensor;
|
||||||
|
|
||||||
|
// We only expect one type of message from controller. But we better check anyway.
|
||||||
|
if (mymsg->type == V_STATUS) {
|
||||||
|
sensor = mymsg->sensor;
|
||||||
|
if (sensor == 1)
|
||||||
|
relay = (relay & 0xFE) + ((mymsg->data[0]=='1')?1:0);
|
||||||
|
if (sensor == 2)
|
||||||
|
relay = (relay & 0xFD) + ((mymsg->data[0]=='1')?2:0);
|
||||||
|
if (sensor == 3)
|
||||||
|
relay = (relay & 0xFB) + ((mymsg->data[0]=='1')?4:0);
|
||||||
|
if (sensor == 4)
|
||||||
|
relay = (relay & 0xF7) + ((mymsg->data[0]=='1')?8:0);
|
||||||
|
if (sensor == 5)
|
||||||
|
relay = (relay & 0xEF) + ((mymsg->data[0]=='1')?0x10:0);
|
||||||
|
if (sensor == 6)
|
||||||
|
relay = (relay & 0xDF) + ((mymsg->data[0]=='1')?0x20:0);
|
||||||
|
if (sensor == 7)
|
||||||
|
relay = (relay & 0xBF) + ((mymsg->data[0]=='1')?0x40:0);
|
||||||
|
if (sensor == 8)
|
||||||
|
relay = (relay & 0x7F) + ((mymsg->data[0]=='1')?0x80:0);
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void present_node(void) {
|
||||||
|
present(NODE_SENSOR_ID, S_ARDUINO_NODE,"Nuvoton Relay Board");
|
||||||
|
sendSketchInfo("Relay_Nuvoton", "1.1");
|
||||||
|
present(1, S_BINARY, "Relay 1");
|
||||||
|
present(2, S_BINARY, "Relay 2");
|
||||||
|
present(3, S_BINARY, "Relay 3");
|
||||||
|
present(4, S_BINARY, "Relay 4");
|
||||||
|
present(5, S_BINARY, "Relay 5");
|
||||||
|
present(6, S_BINARY, "Relay 6");
|
||||||
|
present(7, S_BINARY, "Relay 7");
|
||||||
|
present(8, S_BINARY, "Relay 8");
|
||||||
|
registerNode();
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_loop() {
|
||||||
|
transportProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_init(UINT32 u32Baudrate) //T1M = 1, SMOD = 1
|
||||||
|
{
|
||||||
|
P06_PushPull_Mode;
|
||||||
|
P07_Input_Mode;
|
||||||
|
|
||||||
|
SCON = 0x50; //UART0 Mode1,REN=1,TI=1
|
||||||
|
TMOD |= 0x20; //Timer1 Mode1
|
||||||
|
|
||||||
|
set_SMOD; //UART0 Double Rate Enable
|
||||||
|
set_T1M;
|
||||||
|
clr_BRCK; //Serial port 0 baud rate clock source = Timer1
|
||||||
|
|
||||||
|
#ifdef FOSC_160000
|
||||||
|
TH1 = 256 - (1000000 / u32Baudrate + 1); /*16 MHz */
|
||||||
|
#endif
|
||||||
|
#ifdef FOSC_166000
|
||||||
|
TH1 = 256 - (1037500 / u32Baudrate); /*16.6 MHz */
|
||||||
|
#endif
|
||||||
|
set_TR1;
|
||||||
|
set_TI; //For printf function must setting TI = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uart_init(9600);
|
||||||
|
|
||||||
|
RS485_DIR = 0;
|
||||||
|
P05_PushPull_Mode;
|
||||||
|
|
||||||
|
/* Relays */
|
||||||
|
relay = 0;
|
||||||
|
|
||||||
|
M0 = 1;
|
||||||
|
M1 = 1;
|
||||||
|
M2 = 1;
|
||||||
|
|
||||||
|
P01_Quasi_Mode;
|
||||||
|
P03_Quasi_Mode;
|
||||||
|
P04_Quasi_Mode;
|
||||||
|
|
||||||
|
P11_PushPull_Mode;
|
||||||
|
P12_PushPull_Mode;
|
||||||
|
P13_PushPull_Mode;
|
||||||
|
P14_PushPull_Mode;
|
||||||
|
|
||||||
|
load();
|
||||||
|
|
||||||
|
OE = 0;
|
||||||
|
|
||||||
|
transportInitialise();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uart_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
273
boards/chan8.c.old
Normal file
273
boards/chan8.c.old
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
#include <nuvoton/functions.h>
|
||||||
|
#include <nuvoton/N76E003.h>
|
||||||
|
#include <nuvoton/Common.h>
|
||||||
|
#include <nuvoton/SFR_Macro.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define M0 P03
|
||||||
|
#define M1 P04
|
||||||
|
#define M2 P01
|
||||||
|
|
||||||
|
#define RS485_DIR P05
|
||||||
|
|
||||||
|
#define OE P13
|
||||||
|
#define DS P14
|
||||||
|
#define SHCP P11
|
||||||
|
#define STCP P12
|
||||||
|
|
||||||
|
#define MAXCMD 64
|
||||||
|
|
||||||
|
unsigned char relay;
|
||||||
|
|
||||||
|
unsigned char crc;
|
||||||
|
|
||||||
|
unsigned char getchar1(void)
|
||||||
|
{
|
||||||
|
UINT8 c;
|
||||||
|
while (!RI);
|
||||||
|
c = SBUF;
|
||||||
|
RI = 0;
|
||||||
|
return (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int putchar1 (unsigned char c)
|
||||||
|
{
|
||||||
|
crc += c;
|
||||||
|
TI = 0;
|
||||||
|
SBUF = c;
|
||||||
|
while(TI==0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendpkt(unsigned char cmd, unsigned int len, unsigned char *buffer) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
crc = 0;
|
||||||
|
putchar1(0x55);
|
||||||
|
putchar1(0xAA);
|
||||||
|
putchar1(0x03);
|
||||||
|
putchar1(cmd);
|
||||||
|
putchar1(len >> 8);
|
||||||
|
putchar1(len & 0xFF);
|
||||||
|
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
putchar1(buffer[i]);
|
||||||
|
}
|
||||||
|
putchar1(crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(void) {
|
||||||
|
OE = 0;
|
||||||
|
STCP = 0;
|
||||||
|
SHCP = 0;
|
||||||
|
|
||||||
|
DS = (relay & 0x01)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x02)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x04)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x08)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x10)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x20)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x40)? 1 : 0;
|
||||||
|
SHCP = 1;
|
||||||
|
SHCP = 0;
|
||||||
|
DS = (relay & 0x80)? 1 : 0;
|
||||||
|
|
||||||
|
SHCP = 1;
|
||||||
|
STCP = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tuya_receive (unsigned int len, unsigned char *buffer) {
|
||||||
|
unsigned char dpid;
|
||||||
|
unsigned char dtype;
|
||||||
|
unsigned int dlen;
|
||||||
|
|
||||||
|
if (len < 4) return;
|
||||||
|
dpid = buffer[0];
|
||||||
|
dtype = buffer[1];
|
||||||
|
dlen = buffer[2] << 8 + buffer[3];
|
||||||
|
|
||||||
|
switch(dpid) {
|
||||||
|
case 1:
|
||||||
|
relay = (relay & 0xFE) | (buffer[4] ? 1 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
relay = (relay & 0xFD) | (buffer[4] ? 2 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
relay = (relay & 0xFB) | (buffer[4] ? 4 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
relay = (relay & 0xF7) | (buffer[4] ? 8 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
relay = (relay & 0xEF) | (buffer[4] ? 0x10 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
relay = (relay & 0xDF) | (buffer[4] ? 0x20 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
relay = (relay & 0xBF) | (buffer[4] ? 0x40 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
relay = (relay & 0x7F) | (buffer[4] ? 0x80 : 0);
|
||||||
|
load();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendpkt(7, len, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process(unsigned char cmd, unsigned int len, unsigned char *buffer) {
|
||||||
|
static unsigned char restart = 0;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case 0: /* Heartbeat */
|
||||||
|
buffer[0] = restart;
|
||||||
|
restart = 1;
|
||||||
|
sendpkt(0, 1, buffer);
|
||||||
|
break;
|
||||||
|
case 1: /* Identify */
|
||||||
|
strcpy(buffer,"Nuovo");
|
||||||
|
len = strlen(buffer);
|
||||||
|
sendpkt(1, len, buffer);
|
||||||
|
break;
|
||||||
|
case 3: /* WIFI State */
|
||||||
|
sendpkt(3, 0, NULL);
|
||||||
|
break;
|
||||||
|
case 6: /* Set Command */
|
||||||
|
tuya_receive(len, buffer);
|
||||||
|
break;
|
||||||
|
case 8: /* Query Command */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void recvpkt(void)
|
||||||
|
{
|
||||||
|
static unsigned char state = 0;
|
||||||
|
static unsigned char cmd;
|
||||||
|
static unsigned int len;
|
||||||
|
static unsigned char rcrc;
|
||||||
|
static unsigned char i;
|
||||||
|
static unsigned char command[MAXCMD];
|
||||||
|
|
||||||
|
if (RI) {
|
||||||
|
int inByte = getchar1();
|
||||||
|
switch (state) {
|
||||||
|
case 0:
|
||||||
|
if (inByte == 0x55) state++;
|
||||||
|
rcrc = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (inByte == 0xaa) state++; else state = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (inByte == 0) state++; else state = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
cmd = inByte;
|
||||||
|
state++;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
len = inByte << 8;
|
||||||
|
state++;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
len += inByte;
|
||||||
|
if (len < MAXCMD) state++; else state = 0;
|
||||||
|
if (len == 0) state++;
|
||||||
|
i = 0;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
command[i] = inByte;
|
||||||
|
i++;
|
||||||
|
if (len == i) state++;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
if (inByte == rcrc)
|
||||||
|
process(cmd, len, command);
|
||||||
|
state = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rcrc = rcrc + inByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_loop() {
|
||||||
|
recvpkt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_init(UINT32 u32Baudrate) //T1M = 1, SMOD = 1
|
||||||
|
{
|
||||||
|
P06_PushPull_Mode;
|
||||||
|
P07_Input_Mode;
|
||||||
|
|
||||||
|
SCON = 0x50; //UART0 Mode1,REN=1,TI=1
|
||||||
|
TMOD |= 0x20; //Timer1 Mode1
|
||||||
|
|
||||||
|
set_SMOD; //UART0 Double Rate Enable
|
||||||
|
set_T1M;
|
||||||
|
clr_BRCK; //Serial port 0 baud rate clock source = Timer1
|
||||||
|
|
||||||
|
#ifdef FOSC_160000
|
||||||
|
TH1 = 256 - (1000000 / u32Baudrate + 1); /*16 MHz */
|
||||||
|
#endif
|
||||||
|
#ifdef FOSC_166000
|
||||||
|
TH1 = 256 - (1037500 / u32Baudrate); /*16.6 MHz */
|
||||||
|
#endif
|
||||||
|
set_TR1;
|
||||||
|
set_TI; //For printf function must setting TI = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uart_init(9600);
|
||||||
|
|
||||||
|
RS485_DIR = 0;
|
||||||
|
P05_PushPull_Mode;
|
||||||
|
|
||||||
|
/* Relays */
|
||||||
|
relay = 16;
|
||||||
|
|
||||||
|
M0 = 1;
|
||||||
|
M1 = 1;
|
||||||
|
M2 = 1;
|
||||||
|
|
||||||
|
P01_Quasi_Mode;
|
||||||
|
P03_Quasi_Mode;
|
||||||
|
P04_Quasi_Mode;
|
||||||
|
|
||||||
|
P11_PushPull_Mode;
|
||||||
|
P12_PushPull_Mode;
|
||||||
|
P13_PushPull_Mode;
|
||||||
|
P14_PushPull_Mode;
|
||||||
|
|
||||||
|
load();
|
||||||
|
|
||||||
|
OE = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uart_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include <nuvoton/functions.h>
|
#include <nuvoton/functions.h>
|
||||||
#include <nuvoton/N76E003.h>
|
#include <nuvoton/N76E003.h>
|
||||||
#include <nuvoton/Common.h>
|
#include <nuvoton/Common.h>
|
||||||
#include <nuvoton/Delay.h>
|
|
||||||
#include <nuvoton/SFR_Macro.h>
|
#include <nuvoton/SFR_Macro.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
106
boards/rs485relay.c
Normal file
106
boards/rs485relay.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#include <nuvoton/functions.h>
|
||||||
|
#include <nuvoton/N76E003.h>
|
||||||
|
#include <nuvoton/Common.h>
|
||||||
|
#include <nuvoton/SFR_Macro.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MySensors.h"
|
||||||
|
|
||||||
|
#define RS485_DIR P14
|
||||||
|
|
||||||
|
#define IN1 P05
|
||||||
|
#define IN2 P15
|
||||||
|
|
||||||
|
#define RELAY1 P13
|
||||||
|
#define RELAY2 P01
|
||||||
|
|
||||||
|
#define MAXCMD 64
|
||||||
|
|
||||||
|
unsigned char relay;
|
||||||
|
|
||||||
|
unsigned char crc;
|
||||||
|
|
||||||
|
void rs485_in(void) {
|
||||||
|
RS485_DIR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rs485_out(void) {
|
||||||
|
RS485_DIR = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void receive(const MyMessage* mymsg)
|
||||||
|
{
|
||||||
|
uint8_t sensor;
|
||||||
|
|
||||||
|
// We only expect one type of message from controller. But we better check anyway.
|
||||||
|
if (mymsg->type == V_STATUS) {
|
||||||
|
sensor = mymsg->sensor;
|
||||||
|
if (sensor == 3)
|
||||||
|
RELAY1 = (mymsg->data[0]=='1')?1:0;
|
||||||
|
if (sensor == 4)
|
||||||
|
RELAY2 = (mymsg->data[0]=='1')?1:0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void present_node(void) {
|
||||||
|
present(NODE_SENSOR_ID, S_ARDUINO_NODE,"Nuvoton Relay Board");
|
||||||
|
sendSketchInfo("Relay_Nuvoton", "1.1");
|
||||||
|
present(1, S_DOOR, "IN1");
|
||||||
|
present(2, S_DOOR, "IB2");
|
||||||
|
present(3, S_BINARY, "Relay 1");
|
||||||
|
present(4, S_BINARY, "Relay 2");
|
||||||
|
registerNode();
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_loop() {
|
||||||
|
transportProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_init(UINT32 u32Baudrate) //T1M = 1, SMOD = 1
|
||||||
|
{
|
||||||
|
P06_PushPull_Mode;
|
||||||
|
P07_Input_Mode;
|
||||||
|
|
||||||
|
SCON = 0x50; //UART0 Mode1,REN=1,TI=1
|
||||||
|
TMOD |= 0x20; //Timer1 Mode1
|
||||||
|
|
||||||
|
set_SMOD; //UART0 Double Rate Enable
|
||||||
|
set_T1M;
|
||||||
|
clr_BRCK; //Serial port 0 baud rate clock source = Timer1
|
||||||
|
|
||||||
|
#ifdef FOSC_160000
|
||||||
|
TH1 = 256 - (1000000 / u32Baudrate + 1); /*16 MHz */
|
||||||
|
#endif
|
||||||
|
#ifdef FOSC_166000
|
||||||
|
TH1 = 256 - (1037500 / u32Baudrate); /*16.6 MHz */
|
||||||
|
#endif
|
||||||
|
set_TR1;
|
||||||
|
set_TI; //For printf function must setting TI = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uart_init(9600);
|
||||||
|
|
||||||
|
RS485_DIR = 0;
|
||||||
|
P13_PushPull_Mode;
|
||||||
|
|
||||||
|
/* Relays */
|
||||||
|
RELAY1 = 0;
|
||||||
|
RELAY2 = 0;
|
||||||
|
|
||||||
|
P01_PushPull_Mode;
|
||||||
|
P13_PushPull_Mode;
|
||||||
|
|
||||||
|
/* Inputs */
|
||||||
|
P05_Input_Mode;
|
||||||
|
P15_Input_Mode;
|
||||||
|
|
||||||
|
transportInitialise();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uart_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
void Timer0_Delay100us(UINT32 u32CNT);
|
|
||||||
void Timer0_Delay1ms(UINT32 u32CNT);
|
|
||||||
void Timer1_Delay10ms(UINT32 u32CNT);
|
|
||||||
void Timer2_Delay500us(UINT32 u32CNT);
|
|
||||||
void Timer3_Delay100ms(UINT32 u32CNT);
|
|
||||||
|
|
||||||
void Timer0_Delay40ms(UINT32 u32CNT);
|
|
||||||
void Timer3_Delay10us(UINT32 u32CNT);
|
|
|
@ -1 +0,0 @@
|
||||||
sdcc -mmcs51 -o 2relays.ihx main.c -D FOSC_160000 -I../include
|
|
|
@ -9,8 +9,12 @@
|
||||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include <stdint.h>
|
|
||||||
#include "n76e003.h"
|
#include <nuvoton/functions.h>
|
||||||
|
#include <nuvoton/N76E003.h>
|
||||||
|
#include <nuvoton/Common.h>
|
||||||
|
#include <nuvoton/Delay.h>
|
||||||
|
#include <nuvoton/SFR_Macro.h>
|
||||||
|
|
||||||
// 16Mhz clock
|
// 16Mhz clock
|
||||||
#define CLOCK 16000000L
|
#define CLOCK 16000000L
|
||||||
|
@ -19,14 +23,14 @@
|
||||||
// Per milisecond
|
// Per milisecond
|
||||||
#define T0_1MS ((T0CLOCK)/1000L)
|
#define T0_1MS ((T0CLOCK)/1000L)
|
||||||
|
|
||||||
static void msdelay(uint32_t count)
|
static void msdelay(unsigned long int count)
|
||||||
{
|
{
|
||||||
int16_t reload = -T0_1MS;
|
int reload = -T0_1MS;
|
||||||
|
|
||||||
// Input = Fsys/12
|
// Input = Fsys/12
|
||||||
SET_FIELD(CKCON, T0M, 0);
|
clr_T0M;
|
||||||
// Mode 1
|
// Mode 1
|
||||||
SET_FIELD(TMOD, T0M, 1);
|
set_GATE_T0;
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
TR0 = 1;
|
TR0 = 1;
|
||||||
|
|
1
n76e003_blink/build.sh
Executable file
1
n76e003_blink/build.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
sdcc -mmcs51 -o blink_raw.ihx blink_raw.c -D FOSC_160000 -I../include
|
|
@ -1,403 +0,0 @@
|
||||||
/* Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef N76E003_H
|
|
||||||
#define N76E003_H
|
|
||||||
#include <compiler.h>
|
|
||||||
|
|
||||||
#define DEFINE_FIELD(reg, field, bit, len) \
|
|
||||||
reg##_##field##_Pos = (bit), \
|
|
||||||
reg##_##field##_Msk = (((1 << (len)) - 1) << (bit)),
|
|
||||||
#define GET_FIELD(reg, field) \
|
|
||||||
(((reg) & reg##_##field##_Msk) >> reg##_##field##_Pos)
|
|
||||||
#define SET_FIELD(reg, field, val) \
|
|
||||||
do { \
|
|
||||||
(reg) = ((reg) & ~(reg##_##field##_Msk)) | \
|
|
||||||
(((val) << (reg##_##field##_Pos)) & (reg##_##field##_Msk)); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
SFR(P0, 0x80);
|
|
||||||
SFR(SP, 0x81);
|
|
||||||
SFR(DPL, 0x82);
|
|
||||||
SFR(DPH, 0x83);
|
|
||||||
SFR(RCTRIM0, 0x84);
|
|
||||||
SFR(RCTRIM1, 0x85);
|
|
||||||
SFR(RWK, 0x86);
|
|
||||||
|
|
||||||
SFR(PCON, 0x87);
|
|
||||||
enum {
|
|
||||||
DEFINE_FIELD(PCON, SMOD, 7, 1)
|
|
||||||
DEFINE_FIELD(PCON, SMOD0, 6, 1)
|
|
||||||
DEFINE_FIELD(PCON, POF, 4, 1)
|
|
||||||
DEFINE_FIELD(PCON, GF1, 3, 1)
|
|
||||||
DEFINE_FIELD(PCON, GF0, 2, 1)
|
|
||||||
DEFINE_FIELD(PCON, PD, 1, 1)
|
|
||||||
DEFINE_FIELD(PCON, IDL, 0, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
SFR(TCON, 0x88);
|
|
||||||
SFR(TMOD, 0x89);
|
|
||||||
enum {
|
|
||||||
DEFINE_FIELD(TMOD, T0M, 0, 2)
|
|
||||||
DEFINE_FIELD(TMOD, T0CT, 2, 1)
|
|
||||||
DEFINE_FIELD(TMOD, T0GATE, 3, 1)
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_FIELD(TMOD, T1M, 4, 2)
|
|
||||||
DEFINE_FIELD(TMOD, T1CT, 6, 1)
|
|
||||||
DEFINE_FIELD(TMOD, T1GATE, 7, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
SFR(TL0, 0x8A);
|
|
||||||
SFR(TL1, 0x8B);
|
|
||||||
SFR(TH0, 0x8C);
|
|
||||||
SFR(TH1, 0x8D);
|
|
||||||
SFR(CKCON, 0x8E);
|
|
||||||
enum {
|
|
||||||
DEFINE_FIELD(CKCON, PWMCKS, 6, 1)
|
|
||||||
DEFINE_FIELD(CKCON, T1M, 4, 1)
|
|
||||||
DEFINE_FIELD(CKCON, T0M, 3, 1)
|
|
||||||
DEFINE_FIELD(CKCON, CLOEN, 1, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
SFR(WKCON, 0x8F);
|
|
||||||
|
|
||||||
SFR(P1, 0x90);
|
|
||||||
SFR(SFRS, 0x91); //TA Protection
|
|
||||||
SFR(CAPCON0, 0x92);
|
|
||||||
SFR(CAPCON1, 0x93);
|
|
||||||
SFR(CAPCON2, 0x94);
|
|
||||||
SFR(CKDIV, 0x95);
|
|
||||||
SFR(CKSWT, 0x96); //TA Protection
|
|
||||||
SFR(CKEN, 0x97); //TA Protection
|
|
||||||
|
|
||||||
SFR(SCON, 0x98);
|
|
||||||
SFR(SBUF, 0x99);
|
|
||||||
SFR(SBUF_1, 0x9A);
|
|
||||||
SFR(EIE, 0x9B);
|
|
||||||
SFR(EIE1, 0x9C);
|
|
||||||
SFR(CHPCON, 0x9F); //TA Protection
|
|
||||||
|
|
||||||
enum {
|
|
||||||
EIE_ET2_BIT = (1 << 7),
|
|
||||||
EIE_ESPI_BIT = (1 << 6),
|
|
||||||
EIE_EFB_BIT = (1 << 5),
|
|
||||||
EIE_EWDT_BIT = (1 << 4),
|
|
||||||
EIE_EPWM_BIT = (1 << 3),
|
|
||||||
EIE_ECAP_BIT = (1 << 2),
|
|
||||||
EIE_EPI_BIT = (1 << 1),
|
|
||||||
EIE_EI2C_BIT = (1 << 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
SFR(P2, 0xA0);
|
|
||||||
SFR(AUXR1, 0xA2);
|
|
||||||
SFR(BODCON0, 0xA3); //TA Protection
|
|
||||||
SFR(IAPTRG, 0xA4); //TA Protection
|
|
||||||
SFR(IAPUEN, 0xA5); //TA Protection
|
|
||||||
SFR(IAPAL, 0xA6);
|
|
||||||
SFR(IAPAH, 0xA7);
|
|
||||||
|
|
||||||
SFR(IE, 0xA8);
|
|
||||||
SFR(SADDR, 0xA9);
|
|
||||||
SFR(WDCON, 0xAA); //TA Protection
|
|
||||||
SFR(BODCON1, 0xAB); //TA Protection
|
|
||||||
SFR(P3M1, 0xAC);
|
|
||||||
SFR(P3S, 0xAC); //Page1
|
|
||||||
SFR(P3M2, 0xAD);
|
|
||||||
SFR(P3SR, 0xAD); //Page1
|
|
||||||
SFR(IAPFD, 0xAE);
|
|
||||||
SFR(IAPCN, 0xAF);
|
|
||||||
|
|
||||||
SFR(P3, 0xB0);
|
|
||||||
SFR(P0M1, 0xB1);
|
|
||||||
SFR(P0S, 0xB1); //Page1
|
|
||||||
SFR(P0M2, 0xB2);
|
|
||||||
SFR(P0SR, 0xB2); //Page1
|
|
||||||
SFR(P1M1, 0xB3);
|
|
||||||
SFR(P1S, 0xB3); //Page1
|
|
||||||
SFR(P1M2, 0xB4);
|
|
||||||
SFR(P1SR, 0xB4); //Page1
|
|
||||||
SFR(P2S, 0xB5);
|
|
||||||
SFR(IPH, 0xB7);
|
|
||||||
SFR(PWMINTC, 0xB7); //Page1
|
|
||||||
|
|
||||||
SFR(IP, 0xB8);
|
|
||||||
SFR(SADEN, 0xB9);
|
|
||||||
SFR(SADEN_1, 0xBA);
|
|
||||||
SFR(SADDR_1, 0xBB);
|
|
||||||
|
|
||||||
SFR(I2DAT, 0xBC);
|
|
||||||
SFR(I2STAT, 0xBD);
|
|
||||||
SFR(I2CLK, 0xBE);
|
|
||||||
SFR(I2TOC, 0xBF);
|
|
||||||
SFR(I2CON, 0xC0);
|
|
||||||
SFR(I2ADDR, 0xC1);
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
I2CSTAT_BUS_ERROR = 0x00,
|
|
||||||
I2CSTAT_BUS_RELEASED = 0xF8,
|
|
||||||
|
|
||||||
I2CSTAT_M_START = 0x08,
|
|
||||||
I2CSTAT_M_REPEAT_START = 0x10,
|
|
||||||
I2CSTAT_M_TX_ADDR_ACK = 0x18,
|
|
||||||
I2CSTAT_M_TX_ADDR_NACK = 0x20,
|
|
||||||
I2CSTAT_M_TX_DATA_ACK = 0x28,
|
|
||||||
I2CSTAT_M_TX_DATA_NACK = 0x30,
|
|
||||||
I2CSTAT_M_ARB_LOST = 0x38,
|
|
||||||
I2CSTAT_M_RX_ADDR_ACK = 0x40,
|
|
||||||
I2CSTAT_M_RX_ADDR_NACK = 0x48,
|
|
||||||
I2CSTAT_M_RX_DATA_ACK = 0x50,
|
|
||||||
I2CSTAT_M_RX_DATA_NACK = 0x58,
|
|
||||||
|
|
||||||
|
|
||||||
I2CSTAT_S_TX_REPEAT_START_OR_STOP = 0xA0,
|
|
||||||
I2CSTAT_S_TX_ARB_LOST = 0xB0,
|
|
||||||
I2CSTAT_S_TX_DATA_ACK = 0xB8,
|
|
||||||
I2CSTAT_S_TX_DATA_NACK = 0xC0,
|
|
||||||
I2CSTAT_S_TX_LAST_DATA_ACK = 0xC8,
|
|
||||||
I2CSTAT_S_RX_ACK = 0x60,
|
|
||||||
I2CSTAT_S_RX_ARB_LOST = 0x68,
|
|
||||||
I2CSTAT_S_RX_DATA_ACK = 0x80,
|
|
||||||
I2CSTAT_S_RX_DATA_NACK = 0x88,
|
|
||||||
|
|
||||||
I2CSTAT_GC_ADDR_ACK = 0x70,
|
|
||||||
I2CSTAT_GC_ARB_LOST = 0x78,
|
|
||||||
I2CSTAT_GC_DATA_ACK = 0x90,
|
|
||||||
I2CSTAT_GC_DATA_NACK = 0x98,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
SFR(ADCRL, 0xC2);
|
|
||||||
SFR(ADCRH, 0xC3);
|
|
||||||
SFR(T3CON, 0xC4);
|
|
||||||
enum {
|
|
||||||
DEFINE_FIELD(T3CON, SMOD_1, 7, 1)
|
|
||||||
DEFINE_FIELD(T3CON, SMOD0_1, 6, 1)
|
|
||||||
DEFINE_FIELD(T3CON, BRCK, 5, 1)
|
|
||||||
DEFINE_FIELD(T3CON, TF3, 4, 1)
|
|
||||||
DEFINE_FIELD(T3CON, TR3, 3, 1)
|
|
||||||
DEFINE_FIELD(T3CON, T3PS, 0, 3)
|
|
||||||
};
|
|
||||||
|
|
||||||
SFR(PWM4H, 0xC4); //Page1
|
|
||||||
SFR(RL3, 0xC5);
|
|
||||||
SFR(PWM5H, 0xC5); //Page1
|
|
||||||
SFR(RH3, 0xC6);
|
|
||||||
SFR(PIOCON1, 0xC6); //Page1
|
|
||||||
SFR(TA, 0xC7);
|
|
||||||
|
|
||||||
SFR(T2CON, 0xC8);
|
|
||||||
SFR(T2MOD, 0xC9);
|
|
||||||
SFR(RCMP2L, 0xCA);
|
|
||||||
SFR(RCMP2H, 0xCB);
|
|
||||||
SFR(TL2, 0xCC);
|
|
||||||
SFR(PWM4L, 0xCC); //Page1
|
|
||||||
SFR(TH2, 0xCD);
|
|
||||||
SFR(PWM5L, 0xCD); //Page1
|
|
||||||
SFR(ADCMPL, 0xCE);
|
|
||||||
SFR(ADCMPH, 0xCF);
|
|
||||||
|
|
||||||
SFR(PSW, 0xD0);
|
|
||||||
SFR(PWMPH, 0xD1);
|
|
||||||
SFR(PWM0H, 0xD2);
|
|
||||||
SFR(PWM1H, 0xD3);
|
|
||||||
SFR(PWM2H, 0xD4);
|
|
||||||
SFR(PWM3H, 0xD5);
|
|
||||||
SFR(PNP, 0xD6);
|
|
||||||
SFR(FBD, 0xD7);
|
|
||||||
|
|
||||||
SFR(PWMCON0, 0xD8);
|
|
||||||
SFR(PWMPL, 0xD9);
|
|
||||||
SFR(PWM0L, 0xDA);
|
|
||||||
SFR(PWM1L, 0xDB);
|
|
||||||
SFR(PWM2L, 0xDC);
|
|
||||||
SFR(PWM3L, 0xDD);
|
|
||||||
SFR(PIOCON0, 0xDE);
|
|
||||||
SFR(PWMCON1, 0xDF);
|
|
||||||
|
|
||||||
SFR(ACC, 0xE0);
|
|
||||||
SFR(ADCCON1, 0xE1);
|
|
||||||
SFR(ADCCON2, 0xE2);
|
|
||||||
SFR(ADCDLY, 0xE3);
|
|
||||||
SFR(C0L, 0xE4);
|
|
||||||
SFR(C0H, 0xE5);
|
|
||||||
SFR(C1L, 0xE6);
|
|
||||||
SFR(C1H, 0xE7);
|
|
||||||
|
|
||||||
SFR(ADCCON0, 0xE8);
|
|
||||||
SFR(PICON, 0xE9);
|
|
||||||
SFR(PINEN, 0xEA);
|
|
||||||
SFR(PIPEN, 0xEB);
|
|
||||||
SFR(PIF, 0xEC);
|
|
||||||
SFR(C2L, 0xED);
|
|
||||||
SFR(C2H, 0xEE);
|
|
||||||
SFR(EIP, 0xEF);
|
|
||||||
|
|
||||||
SFR(B, 0xF0);
|
|
||||||
SFR(CAPCON3, 0xF1);
|
|
||||||
SFR(CAPCON4, 0xF2);
|
|
||||||
SFR(SPCR, 0xF3);
|
|
||||||
SFR(SPCR2, 0xF3); //Page1
|
|
||||||
SFR(SPSR, 0xF4);
|
|
||||||
SFR(SPDR, 0xF5);
|
|
||||||
SFR(AINDIDS, 0xF6);
|
|
||||||
SFR(EIPH, 0xF7);
|
|
||||||
|
|
||||||
SFR(SCON_1, 0xF8);
|
|
||||||
SFR(PDTEN, 0xF9); //TA Protection
|
|
||||||
SFR(PDTCNT, 0xFA); //TA Protection
|
|
||||||
SFR(PMEN, 0xFB);
|
|
||||||
SFR(PMD, 0xFC);
|
|
||||||
SFR(EIP1, 0xFE);
|
|
||||||
SFR(EIPH1, 0xFF);
|
|
||||||
|
|
||||||
/* BIT Registers */
|
|
||||||
/* SCON_1 */
|
|
||||||
SBIT(SM0_1, 0xF8, 7);
|
|
||||||
SBIT(FE_1, 0xF8, 7);
|
|
||||||
SBIT(SM1_1, 0xF8, 6);
|
|
||||||
SBIT(SM2_1, 0xF8, 5);
|
|
||||||
SBIT(REN_1, 0xF8, 4);
|
|
||||||
SBIT(TB8_1, 0xF8, 3);
|
|
||||||
SBIT(RB8_1, 0xF8, 2);
|
|
||||||
SBIT(TI_1, 0xF8, 1);
|
|
||||||
SBIT(RI_1, 0xF8, 0);
|
|
||||||
|
|
||||||
/* ADCCON0 */
|
|
||||||
SBIT(ADCF, 0xE8, 7);
|
|
||||||
SBIT(ADCS, 0xE8, 6);
|
|
||||||
SBIT(ETGSEL1,0xE8, 5);
|
|
||||||
SBIT(ETGSEL0,0xE8, 4);
|
|
||||||
SBIT(ADCHS3, 0xE8, 3);
|
|
||||||
SBIT(ADCHS2, 0xE8, 2);
|
|
||||||
SBIT(ADCHS1, 0xE8, 1);
|
|
||||||
SBIT(ADCHS0, 0xE8, 0);
|
|
||||||
|
|
||||||
/* PWMCON0 */
|
|
||||||
SBIT(PWMRUN, 0xD8, 7);
|
|
||||||
SBIT(LOAD, 0xD8, 6);
|
|
||||||
SBIT(PWMF, 0xD8, 5);
|
|
||||||
SBIT(CLRPWM, 0xD8, 4);
|
|
||||||
|
|
||||||
|
|
||||||
/* PSW */
|
|
||||||
SBIT(CY, 0xD0, 7);
|
|
||||||
SBIT(AC, 0xD0, 6);
|
|
||||||
SBIT(F0, 0xD0, 5);
|
|
||||||
SBIT(RS1, 0xD0, 4);
|
|
||||||
SBIT(RS0, 0xD0, 3);
|
|
||||||
SBIT(OV, 0xD0, 2);
|
|
||||||
SBIT(P, 0xD0, 0);
|
|
||||||
/* T2CON */
|
|
||||||
SBIT(TF2, 0xC8, 7);
|
|
||||||
SBIT(TR2, 0xC8, 2);
|
|
||||||
SBIT(CM_RL2, 0xC8, 0);
|
|
||||||
|
|
||||||
/* I2CON
|
|
||||||
* Naming differs from Nuvoton headers:
|
|
||||||
* I2C prefixes added to ambiguous bits
|
|
||||||
*/
|
|
||||||
SBIT(I2CEN, 0xC0, 6);
|
|
||||||
SBIT(I2CSTA, 0xC0, 5);
|
|
||||||
SBIT(I2CSTO, 0xC0, 4);
|
|
||||||
SBIT(I2CSI, 0xC0, 3);
|
|
||||||
SBIT(I2CAA, 0xC0, 2);
|
|
||||||
SBIT(I2CPX, 0xC0, 0);
|
|
||||||
|
|
||||||
/* IP */
|
|
||||||
SBIT(PADC, 0xB8, 6);
|
|
||||||
SBIT(PBOD, 0xB8, 5);
|
|
||||||
SBIT(PS, 0xB8, 4);
|
|
||||||
SBIT(PT1, 0xB8, 3);
|
|
||||||
SBIT(PX1, 0xB8, 2);
|
|
||||||
SBIT(PT0, 0xB8, 1);
|
|
||||||
SBIT(PX0, 0xB8, 0);
|
|
||||||
|
|
||||||
/* P3 */
|
|
||||||
SBIT(P30, 0xB0, 0);
|
|
||||||
|
|
||||||
|
|
||||||
/* IE */
|
|
||||||
SBIT(EA, 0xA8, 7);
|
|
||||||
SBIT(EADC, 0xA8, 6);
|
|
||||||
SBIT(EBOD, 0xA8, 5);
|
|
||||||
SBIT(ES, 0xA8, 4);
|
|
||||||
SBIT(ET1, 0xA8, 3);
|
|
||||||
SBIT(EX1, 0xA8, 2);
|
|
||||||
SBIT(ET0, 0xA8, 1);
|
|
||||||
SBIT(EX0, 0xA8, 0);
|
|
||||||
|
|
||||||
/* P2 */
|
|
||||||
SBIT(P20, 0xA0, 0);
|
|
||||||
|
|
||||||
/* SCON */
|
|
||||||
SBIT(SM0, 0x98, 7);
|
|
||||||
SBIT(FE, 0x98, 7);
|
|
||||||
SBIT(SM1, 0x98, 6);
|
|
||||||
SBIT(SM2, 0x98, 5);
|
|
||||||
SBIT(REN, 0x98, 4);
|
|
||||||
SBIT(TB8, 0x98, 3);
|
|
||||||
SBIT(RB8, 0x98, 2);
|
|
||||||
SBIT(TI, 0x98, 1);
|
|
||||||
SBIT(RI, 0x98, 0);
|
|
||||||
|
|
||||||
/* P1 */
|
|
||||||
SBIT(P17, 0x90, 7);
|
|
||||||
SBIT(P16, 0x90, 6);
|
|
||||||
SBIT(TXD_1, 0x90, 6);
|
|
||||||
SBIT(P15, 0x90, 5);
|
|
||||||
SBIT(P14, 0x90, 4);
|
|
||||||
SBIT(SDA, 0x90, 4);
|
|
||||||
SBIT(P13, 0x90, 3);
|
|
||||||
SBIT(SCL, 0x90, 3);
|
|
||||||
SBIT(P12, 0x90, 2);
|
|
||||||
SBIT(P11, 0x90, 1);
|
|
||||||
SBIT(P10, 0x90, 0);
|
|
||||||
|
|
||||||
/* TCON */
|
|
||||||
SBIT(TF1, 0x88, 7);
|
|
||||||
SBIT(TR1, 0x88, 6);
|
|
||||||
SBIT(TF0, 0x88, 5);
|
|
||||||
SBIT(TR0, 0x88, 4);
|
|
||||||
SBIT(IE1, 0x88, 3);
|
|
||||||
SBIT(IT1, 0x88, 2);
|
|
||||||
SBIT(IE0, 0x88, 1);
|
|
||||||
SBIT(IT0, 0x88, 0);
|
|
||||||
|
|
||||||
/* P0 */
|
|
||||||
|
|
||||||
SBIT(P07, 0x80, 7);
|
|
||||||
SBIT(RXD, 0x80, 7);
|
|
||||||
SBIT(P06, 0x80, 6);
|
|
||||||
SBIT(TXD, 0x80, 6);
|
|
||||||
SBIT(P05, 0x80, 5);
|
|
||||||
SBIT(P04, 0x80, 4);
|
|
||||||
SBIT(STADC, 0x80, 4);
|
|
||||||
SBIT(P03, 0x80, 3);
|
|
||||||
SBIT(P02, 0x80, 2);
|
|
||||||
SBIT(RXD_1, 0x80, 2);
|
|
||||||
SBIT(P01, 0x80, 1);
|
|
||||||
SBIT(MISO, 0x80, 1);
|
|
||||||
SBIT(P00, 0x80, 0);
|
|
||||||
SBIT(MOSI, 0x80, 0);
|
|
||||||
|
|
||||||
#define TA_UNPROTECT() do { \
|
|
||||||
TA = 0xAA; \
|
|
||||||
TA = 0x55; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define SFR_PAGE(n) do { \
|
|
||||||
TA_UNPROTECT(); \
|
|
||||||
SFRS = n; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue