From efa5673e716cdd1cd97ca1286db3ff6d4a98e92a Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Sat, 27 Mar 2021 18:23:58 +0100 Subject: [PATCH] Sync work --- boards/MySensors.c | 487 ++++++++++++++++++ boards/MySensors.h | 320 ++++++++++++ boards.txt => boards/boards.txt | 0 boards/build.sh | 5 + boards/chan8.c | 167 ++++++ boards/chan8.c.old | 273 ++++++++++ {lctech-relay-altfw => boards}/config.json | 0 lctech-relay-altfw/main.c => boards/lc.c | 1 - boards/rs485relay.c | 106 ++++ .../main.c => boards/rs485relay.c.old | 0 include/nuvoton/Delay.h | 8 - lctech-relay-altfw/build.sh | 1 - n76e003_blink/blink_raw.c | 16 +- n76e003_blink/build.sh | 1 + n76e003_blink/n76e003.h | 403 --------------- 15 files changed, 1369 insertions(+), 419 deletions(-) create mode 100644 boards/MySensors.c create mode 100644 boards/MySensors.h rename boards.txt => boards/boards.txt (100%) create mode 100755 boards/build.sh create mode 100644 boards/chan8.c create mode 100644 boards/chan8.c.old rename {lctech-relay-altfw => boards}/config.json (100%) rename lctech-relay-altfw/main.c => boards/lc.c (99%) create mode 100644 boards/rs485relay.c rename relay-tuyafw/main.c => boards/rs485relay.c.old (100%) delete mode 100644 include/nuvoton/Delay.h delete mode 100755 lctech-relay-altfw/build.sh create mode 100755 n76e003_blink/build.sh delete mode 100644 n76e003_blink/n76e003.h diff --git a/boards/MySensors.c b/boards/MySensors.c new file mode 100644 index 0000000..0a193a9 --- /dev/null +++ b/boards/MySensors.c @@ -0,0 +1,487 @@ +#include +#include +#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; wdestination; + 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 +#include + +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
+ * 1 bit - Signed flag
+ * 5 bit - Length of payload + */ + uint8_t version_length; + + /** + * 3 bit - Command type
+ * 1 bit - Request an echo - Indicator that receiver should echo the message back to the sender
+ * 1 bit - Is echo message - Indicator that this is the echoed message
+ * 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 diff --git a/boards.txt b/boards/boards.txt similarity index 100% rename from boards.txt rename to boards/boards.txt diff --git a/boards/build.sh b/boards/build.sh new file mode 100755 index 0000000..19c8d12 --- /dev/null +++ b/boards/build.sh @@ -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 diff --git a/boards/chan8.c b/boards/chan8.c new file mode 100644 index 0000000..3212852 --- /dev/null +++ b/boards/chan8.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#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(); + } +} + diff --git a/boards/chan8.c.old b/boards/chan8.c.old new file mode 100644 index 0000000..2a2f09a --- /dev/null +++ b/boards/chan8.c.old @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include + +#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 #include #include -#include #include #include diff --git a/boards/rs485relay.c b/boards/rs485relay.c new file mode 100644 index 0000000..6a3f126 --- /dev/null +++ b/boards/rs485relay.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#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(); + } +} + diff --git a/relay-tuyafw/main.c b/boards/rs485relay.c.old similarity index 100% rename from relay-tuyafw/main.c rename to boards/rs485relay.c.old diff --git a/include/nuvoton/Delay.h b/include/nuvoton/Delay.h deleted file mode 100644 index e2eef90..0000000 --- a/include/nuvoton/Delay.h +++ /dev/null @@ -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); \ No newline at end of file diff --git a/lctech-relay-altfw/build.sh b/lctech-relay-altfw/build.sh deleted file mode 100755 index d58c2b5..0000000 --- a/lctech-relay-altfw/build.sh +++ /dev/null @@ -1 +0,0 @@ -sdcc -mmcs51 -o 2relays.ihx main.c -D FOSC_160000 -I../include diff --git a/n76e003_blink/blink_raw.c b/n76e003_blink/blink_raw.c index 0fd9d9a..e2979c9 100644 --- a/n76e003_blink/blink_raw.c +++ b/n76e003_blink/blink_raw.c @@ -9,8 +9,12 @@ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -#include -#include "n76e003.h" + +#include +#include +#include +#include +#include // 16Mhz clock #define CLOCK 16000000L @@ -19,14 +23,14 @@ // Per milisecond #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 - SET_FIELD(CKCON, T0M, 0); + clr_T0M; // Mode 1 - SET_FIELD(TMOD, T0M, 1); + set_GATE_T0; // Start TR0 = 1; diff --git a/n76e003_blink/build.sh b/n76e003_blink/build.sh new file mode 100755 index 0000000..9ef0c15 --- /dev/null +++ b/n76e003_blink/build.sh @@ -0,0 +1 @@ +sdcc -mmcs51 -o blink_raw.ihx blink_raw.c -D FOSC_160000 -I../include diff --git a/n76e003_blink/n76e003.h b/n76e003_blink/n76e003.h deleted file mode 100644 index 19cc2f1..0000000 --- a/n76e003_blink/n76e003.h +++ /dev/null @@ -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 - -#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