The Wall Unit and Corridor Door Dome LEDs operate as standard Modbus RTU Slaves on an industrial half-duplex RS-485 bus.
| Parameter | Value | Hardware Engineering Notes |
|---|---|---|
| Physical Wiring | A+, B-, GND (2-Wire Half-Duplex) |
TVS surge suppression diodes recommended on lines. |
| Baud Rate | 19200 bps | Standard default (Configurable: 9600, 19200, 38400, 115200). |
| Framing | 8-N-1 | 8 Data Bits, No Parity, 1 Stop Bit. |
| CRC Checksum | CRC-16 IBM (0xA001) | Standard Modbus RTU CRC (Low Byte transmitted first). |
| Factory Default Slave ID | 255 (0xFF) | Unit ships in unprovisioned state out of the box. |
| Assigned Slave ID Range | 1 to 247 | Written into EEPROM during Interactive Discovery. |
| Broadcast Address | 0 (0x00) | Used by Master to trigger Discovery Mode. |
| Turnaround Response Time | < 20 ms | Microcontroller response delay after receiving Master request. |
| RS-485 DE/~RE Pin Control | Hardware GPIO Pin | Set DE High ≥ 1ms before TX. Drive DE Low only after TX Complete (TC flag). |
Buttons are indexed in standard reading order (Top-Left → Top-Right → Bottom-Left → Bottom-Right):
TOILET_IN. Contact closed to GND triggers Bit 12 = 1.The hardware uses 3 microcontroller GPIO pins (Red, Green, Blue) to produce 7 pure digital colors (Simple ON/OFF logic):
| Color Code | Color Name | Red GPIO Pin | Green GPIO Pin | Blue GPIO Pin | Hospital Visual Use Case |
|---|---|---|---|---|---|
| 0 | OFF | 0 (LOW) |
0 (LOW) |
0 (LOW) |
LED turned off / Clean mode |
| 1 | RED | 1 (HIGH) | 0 (LOW) |
0 (LOW) |
Code Blue / Emergency SOS |
| 2 | GREEN | 0 (LOW) |
1 (HIGH) | 0 (LOW) |
Care Started / Nurse Present |
| 3 | BLUE | 0 (LOW) |
0 (LOW) |
1 (HIGH) | Extra Help / Active Idle Heartbeat Glow |
| 4 | YELLOW | 1 (HIGH) | 1 (HIGH) | 0 (LOW) |
Normal Nurse Call |
| 5 | CYAN | 0 (LOW) |
1 (HIGH) | 1 (HIGH) | Housekeeping / Assistance |
| 6 | PURPLE | 1 (HIGH) | 0 (LOW) |
1 (HIGH) | Code Pink / Staff Assist |
| 7 | WHITE | 1 (HIGH) | 1 (HIGH) | 1 (HIGH) | All Pins High / Self-Test |
| PLC Address | Hex Address | Dec | Access | Parameter Name | Description / Bit Allocation |
|---|---|---|---|---|---|
| 40001 | 0x0000 | 0 | READ | Live Button Status Bitmask |
Bit = 1 when pressed / active: • Bit 0: Button 1 Single Press (< 2s) • Bit 1: Button 1 Long Press (> 2s) • Bit 2: Button 2 Single Press • Bit 3: Button 2 Long Press • Bit 4: Button 3 Single Press • Bit 5: Button 3 Long Press • Bit 6: Button 4 Single Press • Bit 7: Button 4 Long Press • Bit 12: Attached Toilet Pull-Cord Triggered • Bit 13: Attached Bedside Handset Button • Bit 14: Tamper Switch Opened |
When the Gateway commissions a device, it writes this complete configuration block into the unit's EEPROM:
| PLC Address | Hex Address | Dec | Access | Storage | Parameter Name | Default | Description |
|---|---|---|---|---|---|---|---|
| 40002 | 0x0001 | 1 | R/W | EEPROM | Single-Press Key Enable Mask | 0x1FFF |
Bit = 1 (Enabled), Bit = 0 (Disabled / Ignored by firmware). |
| 40003 | 0x0002 | 2 | R/W | EEPROM | Long-Press Key Enable Mask | 0x0FFF |
Bit = 1 (Enabled), Bit = 0 (Disabled / Ignored by firmware). |
| 40004 | 0x0003 | 3 | R/W | EEPROM | Long-Press Threshold (ms) | 2000 |
Time in ms required to hold button for Long Press. |
| 40005 | 0x0004 | 4 | R/W | EEPROM | Debounce Time (ms) | 50 |
Hardware debounce filter duration (Default: 50ms). |
| 40006 | 0x0005 | 5 | R/W | EEPROM | Idle / Clean Glow Color | 3 (Blue) |
Color shown when unit is idle/online (3=Blue, 0=OFF). |
| 40021 | 0x0014 | 20 | R/W | EEPROM | Button 1 Single-Press Color | 4 (Yellow) | Color code triggered when Button 1 is single-pressed. |
| 40022 | 0x0015 | 21 | R/W | EEPROM | Button 1 Long-Press Color | 1 (Red) | Color code triggered when Button 1 is long-pressed. |
| 40023 | 0x0016 | 22 | R/W | EEPROM | Button 2 Single-Press Color | 6 (Purple) | Color code triggered when Button 2 is single-pressed. |
| 40024 | 0x0017 | 23 | R/W | EEPROM | Button 2 Long-Press Color | 1 (Red) | Color code triggered when Button 2 is long-pressed. |
| 40025 | 0x0018 | 24 | R/W | EEPROM | Button 3 Single-Press Color | 3 (Blue) | Color code triggered when Button 3 is single-pressed. |
| 40026 | 0x0019 | 25 | R/W | EEPROM | Button 3 Long-Press Color | 1 (Red) | Color code triggered when Button 3 is long-pressed. |
| 40027 | 0x001A | 26 | R/W | EEPROM | Button 4 Single-Press Color | 2 (Green) | Color code triggered when Button 4 is single-pressed. |
| 40028 | 0x001B | 27 | R/W | EEPROM | Button 4 Long-Press Color | 0 (OFF) | Long-press action on Button 4 (e.g. Care Reset). |
| 40029 | 0x001C | 28 | R/W | EEPROM | Attached Toilet Trigger Color | 4 (Yellow) | Color code triggered when Toilet cord is pulled. |
| 40030 | 0x001D | 29 | R/W | EEPROM | Attached Handset Trigger Color | 4 (Yellow) | Color code triggered when Aux Handset is pressed. |
| 40254 | 0x00FD | 253 | R/W | EEPROM | Commissioning Status Flag | 0 (Pending) |
0: Factory / Uncommissioned State (Pending Setup)1: Commissioned by Gateway (Production Active)
|
| 40255 | 0x00FE | 254 | R/W | RAM | System Discovery Command | 0x0000 |
0x00AA: Discover Uncommissioned Only (Reg 253 == 0)0x00FF: Force Discover ALL Units on Bus0x0000: Normal Operating Mode
|
| 40256 | 0x00FF | 255 | R/W | EEPROM | Modbus Slave ID | 255 |
Assigned Slave ID (1..247). Saved in EEPROM. Sets Reg 253 = 1 & turns Solid Green 3s. |
The Corridor Door Light is an independent Modbus Slave that displays active calls for the room/ward and automatically alternates colors when multiple beds call at once:
| PLC Address | Hex Address | Dec | Access | Parameter Name | Description |
|---|---|---|---|---|---|
| 40001 | 0x0000 | 0 | R/W | Display Mode |
0: Idle / Clean Glow (Shows heartbeat color)1: Single Static Color (Shows Color 1)2: Fast SOS Blinking (Emergency)3: Multi-Call Alternating Cycle (Cycles between Color 1..6)
|
| 40002 | 0x0001 | 1 | R/W | Color 1 (Bed 1) | Color code (0 to 7) for Bed 1 active call |
| 40003 | 0x0002 | 2 | R/W | Color 2 (Bed 2) | Color code (0 to 7) for Bed 2 active call |
| 40004 | 0x0003 | 3 | R/W | Color 3 (Bed 3) | Color code (0 to 7) for Bed 3 active call |
| 40005 | 0x0004 | 4 | R/W | Color 4 (Bed 4) | Color code (0 to 7) for Bed 4 active call |
| 40006 | 0x0005 | 5 | R/W | Color 5 (Bed 5) | Color code for Bed 5 call (6-bed ward) |
| 40007 | 0x0006 | 6 | R/W | Color 6 (Bed 6) | Color code for Bed 6 call (6-bed ward) |
| 40011 | 0x000A | 10 | R/W | Cycle Time (ms) | Time to display each color before alternating (Default: 1500ms) |
| 40012 | 0x000B | 11 | R/W | Idle Heartbeat Color | Color shown when all calls cleared (3=Blue, 0=OFF) |
| 40256 | 0x00FF | 255 | R/W | Slave ID | Modbus Slave ID (1..247). Saved in EEPROM. |
Even if devices arrive from the factory with identical temporary test IDs (e.g. all set to ID 1), our Commissioned Status Flag (Reg 253) guarantees zero collisions:
Only units with Reg 253 == 0 (uncommissioned) will blink. Existing commissioned units ignore the broadcast, ensuring active hospital rooms are not disturbed.
Every unit on the bus blinks regardless of previous state. Used for new ward installations or full re-addressing.
The Gateway sends a standard Modbus RTU Write command to Broadcast Address 0 (`0x00`) writing value 0x00AA or 0x00FF into Register 254 (0x00FE):
Gateway Master Request (New Only): 00 06 00 FE 00 AA 28 69 (Broadcast 0x00, Reg 254 = 0x00AA)
Gateway Master Request (Force All): 00 06 00 FE 00 FF A9 B9 (Broadcast 0x00, Reg 254 = 0x00FF)
The technician walks over to the specific bed (e.g. Bed 101) and presses and holds Button 1 (Top-Left) for 3 seconds.
While discovery is active, the Gateway periodically polls unassigned address 255 (or active discovery pool):
Gateway Master Request: FF 03 00 00 00 01 91 D4 (Read Reg 0 on Slave 255)
Selected Slave Response: FF 03 02 00 AA 11 94 (Reg 0 = 0x00AA -> Unit is Selected!)
The Gateway sends a standard Write Single Register command to Register 255 (0x00FF) with the desired new Slave ID (e.g. 101 / 0x0065):
Gateway Master Request: FF 06 00 FF 00 65 AC 23 (Write Reg 255 = 101 to Slave 255)
Slave Echo Response: FF 06 00 FF 00 65 AC 23 (Slave echoes back confirmation)
101 into internal non-volatile EEPROM memory.is_discovery_mode = false.The Gateway immediately writes the full button RGB colors and key enable masks (Registers 1 to 29) to Slave 101 using standard Modbus Function Code 0x10 (Write Multiple Registers). The unit saves all colors to EEPROM and switches to Clean Idle Glow mode.
// =========================================================================
// MICROCONTROLLER DISCOVERY & SLAVE ID STATE MACHINE (C / C++)
// =========================================================================
enum DeviceState {
STATE_NORMAL_RUNNING, // Normal hospital operation
STATE_DISCOVERY_FLASHING, // Rapid LED blink after receiving Broadcast
STATE_PAIRING_SELECTED, // Technician held Button 1 for 3s
STATE_ID_CONFIRMED // Green 3s confirmation after ID write
};
enum DeviceState current_state = STATE_NORMAL_RUNNING;
uint32_t blink_timer = 0;
bool blink_led_toggle = false;
// 1. In your Main Loop (called continuously):
void loop_discovery_handler() {
// If in Discovery Flashing Mode -> Blink all LEDs at 2.5Hz (200ms ON / 200ms OFF)
if (current_state == STATE_DISCOVERY_FLASHING) {
if (millis() - blink_timer >= 200) {
blink_timer = millis();
blink_led_toggle = !blink_led_toggle;
set_all_leds(blink_led_toggle ? COLOR_CYAN : COLOR_OFF);
}
}
}
// 2. In your Button ISR / Polling Routine:
void on_button1_held_3_seconds() {
// If unit is in Discovery Mode and Button 1 is held 3s -> Select this unit!
if (current_state == STATE_DISCOVERY_FLASHING) {
current_state = STATE_PAIRING_SELECTED;
live_status_reg0 = 0x00AA; // Set Reg 0 = 0x00AA (Signals Gateway)
// Show Solid Yellow on Button 1 to show technician it is selected
set_button_led(0, COLOR_YELLOW);
}
}
// 3. In your Modbus Register Write Callback:
void handle_modbus_register_write(uint8_t slave_addr, uint16_t reg_addr, uint16_t write_val) {
// A. Broadcast Discovery Command (Reg 254 / 0x00FE)
if (reg_addr == 0x00FE) {
if (write_val == 0x00AA) {
// Mode 1: Only uncommissioned units (Reg 253 == 0) blink!
if (config.is_commissioned == 0) {
current_state = STATE_DISCOVERY_FLASHING;
}
} else if (write_val == 0x00FF) {
// Mode 2: Force ALL units on bus to blink!
current_state = STATE_DISCOVERY_FLASHING;
} else if (write_val == 0x0000) {
// Stop discovery
current_state = STATE_NORMAL_RUNNING;
set_all_leds_idle();
}
}
// B. Slave ID Assignment (Reg 255 / 0x00FF)
else if (reg_addr == 0x00FF) {
if (write_val >= 1 && write_val <= 247) {
// 1. Burn new Slave ID and mark as Commissioned in EEPROM
config.slave_id = (uint8_t)write_val;
config.is_commissioned = 1; // Mark as Commissioned (Reg 253)
save_config_to_eeprom();
// 2. Visual & Audible Confirmation
current_state = STATE_ID_CONFIRMED;
set_all_leds(COLOR_GREEN); // Turn ALL LEDs Solid Green
buzzer_beep(200); // 200ms confirmation beep
delay_ms(3000); // Hold Solid Green for 3.0 seconds
// 3. Switch active Modbus listening address to the new ID
modbus_set_slave_address(config.slave_id);
// 4. Return to normal operation
current_state = STATE_NORMAL_RUNNING;
live_status_reg0 = 0x0000;
set_all_leds_idle();
}
}
}
To make it 100% simple for the microcontroller firmware developer, here is the complete EEPROM memory layout that must be allocated in non-volatile Flash/EEPROM:
| EEPROM Offset | Modbus Register | Hex Addr | Data Type | Factory Default | What It Stores & Why |
|---|---|---|---|---|---|
0x00 |
Reg 255 | 0x00FF |
uint8_t |
255 | Slave ID: Modbus address of the device (1 to 247). |
0x01 |
Reg 253 | 0x00FD |
uint8_t |
0 (Pending) | Commissioned Flag: 0 = Factory/Unassigned, 1 = Commissioned by Siscall. |
0x02 |
Reg 1 | 0x0001 |
uint16_t |
0x1FFF (8191) | Single-Press Key Mask: Which buttons are enabled for short press. |
0x04 |
Reg 2 | 0x0002 |
uint16_t |
0x0FFF (4095) | Long-Press Key Mask: Which buttons are enabled for long press. |
0x06 |
Reg 3 | 0x0003 |
uint16_t |
2000 | Long-Press Hold Time: Milliseconds required to hold (e.g. 2000ms). |
0x08 |
Reg 4 | 0x0004 |
uint16_t |
50 | Debounce Time: Hardware debounce filter in ms (e.g. 50ms). |
0x0A |
Reg 5 | 0x0005 |
uint8_t |
3 (Blue) | Idle Glow Color: Backlight color in clean idle state (3=Blue, 0=OFF). |
0x0B |
Reg 20 | 0x0014 |
uint8_t |
4 (Yellow) | Button 1 Single-Press Color: Normal patient nurse call. |
0x0C |
Reg 21 | 0x0015 |
uint8_t |
1 (Red) | Button 1 Long-Press Color: Critical SOS / Code Blue. |
0x0D |
Reg 22 | 0x0016 |
uint8_t |
6 (Purple) | Button 2 Single-Press Color: Staff Alert / Assistance. |
0x0E |
Reg 23 | 0x0017 |
uint8_t |
1 (Red) | Button 2 Long-Press Color: Critical SOS. |
0x0F |
Reg 24 | 0x0018 |
uint8_t |
3 (Blue) | Button 3 Single-Press Color: Doctor Assist / Extra Help. |
0x10 |
Reg 25 | 0x0019 |
uint8_t |
1 (Red) | Button 3 Long-Press Color: Critical SOS. |
0x11 |
Reg 26 | 0x001A |
uint8_t |
2 (Green) | Button 4 Single-Press Color: Nurse Present / Care Started. |
0x12 |
Reg 27 | 0x001B |
uint8_t |
0 (OFF) | Button 4 Long-Press Color: Reset / Care Ended (Turn OFF). |
0x13 |
Reg 28 | 0x001C |
uint8_t |
4 (Yellow) | Attached Toilet Pull-Cord Color: Toilet Emergency. |
0x14 |
Reg 29 | 0x001D |
uint8_t |
4 (Yellow) | Attached Handset Trigger Color: Bedside handset SOS. |
Complete C/C++ firmware skeleton for the hardware microcontroller:
// =========================================================================
// SISCALL PRO - MICROCONTROLLER FIRMWARE REFERENCE IMPLEMENTATION (C / C++)
// =========================================================================
#include <stdint.h>
#include <stdbool.h>
// --- EEPROM Non-Volatile Memory Storage Structure (21 Bytes Total) ---
typedef struct {
uint8_t slave_id; // Reg 255: Default 255 (0xFF)
uint8_t is_commissioned; // Reg 253: 0 = Factory/Uncommissioned, 1 = Commissioned
uint16_t single_press_mask; // Reg 1: Single-press enable bitmask
uint16_t long_press_mask; // Reg 2: Long-press enable bitmask
uint16_t long_press_hold_ms; // Reg 3: Default 2000 ms
uint16_t debounce_ms; // Reg 4: Default 50 ms
uint8_t idle_glow_color; // Reg 5: Default 3 (Blue)
uint8_t btn_sp_color[4]; // Reg 20, 22, 24, 26 (Button 1..4 Single-Press Color)
uint8_t btn_lp_color[4]; // Reg 21, 23, 25, 27 (Button 1..4 Long-Press Color)
uint8_t toilet_color; // Reg 28: Attached Toilet Color (Default 4 = Yellow)
uint8_t handset_color; // Reg 29: Attached Handset Color (Default 4 = Yellow)
} DeviceConfig_t;
DeviceConfig_t config;
uint16_t live_status_reg0 = 0x0000; // Reg 0: Live bitmask read by Gateway
// --- GPIO Pin Output Function for 7-Color Digital RGB ---
void set_rgb_pins(uint8_t red_pin, uint8_t green_pin, uint8_t blue_pin, uint8_t color_code) {
switch(color_code) {
case 0: digitalWrite(red_pin, 0); digitalWrite(green_pin, 0); digitalWrite(blue_pin, 0); break; // OFF
case 1: digitalWrite(red_pin, 1); digitalWrite(green_pin, 0); digitalWrite(blue_pin, 0); break; // RED
case 2: digitalWrite(red_pin, 0); digitalWrite(green_pin, 1); digitalWrite(blue_pin, 0); break; // GREEN
case 3: digitalWrite(red_pin, 0); digitalWrite(green_pin, 0); digitalWrite(blue_pin, 1); break; // BLUE
case 4: digitalWrite(red_pin, 1); digitalWrite(green_pin, 1); digitalWrite(blue_pin, 0); break; // YELLOW
case 5: digitalWrite(red_pin, 0); digitalWrite(green_pin, 1); digitalWrite(blue_pin, 1); break; // CYAN
case 6: digitalWrite(red_pin, 1); digitalWrite(green_pin, 0); digitalWrite(blue_pin, 1); break; // PURPLE
case 7: digitalWrite(red_pin, 1); digitalWrite(green_pin, 1); digitalWrite(blue_pin, 1); break; // WHITE
}
}
// --- Button Timing & State Machine ---
void handle_button_press(uint8_t btn_index, uint32_t hold_duration_ms) {
if (hold_duration_ms >= config.long_press_hold_ms) {
if (config.long_press_mask & (1 << (btn_index * 2 + 1))) {
live_status_reg0 |= (1 << (btn_index * 2 + 1));
set_button_led(btn_index, config.btn_lp_color[btn_index]);
}
} else if (hold_duration_ms >= config.debounce_ms) {
if (config.single_press_mask & (1 << (btn_index * 2))) {
live_status_reg0 |= (1 << (btn_index * 2));
set_button_led(btn_index, config.btn_sp_color[btn_index]);
}
}
}
Master sends Function Code 0x03 to Slave 1, starting at address 0x0000, quantity 1:
Master Request: 01 03 00 00 00 01 84 0A (Slave 1, FC 03, Reg 0, Qty 1, CRC)
Slave Response: 01 03 02 00 01 79 84 (Slave 1, FC 03, 2 Bytes, Value = 0x0001 [Button 1 Pressed], CRC)
Master writes 0x00AA (Pending Only) or 0x00FF (Force All) to Register 254 (0x00FE) using Broadcast address 0x00:
Broadcast New/Pending Only: 00 06 00 FE 00 AA 28 69 (Broadcast 0x00, FC 06, Reg 254 = 0x00AA, CRC)
Broadcast Force ALL Units: 00 06 00 FE 00 FF A9 B9 (Broadcast 0x00, FC 06, Reg 254 = 0x00FF, CRC)
Master writes value 101 (0x0065) to Register 255 (0x00FF):
Master Request: FF 06 00 FF 00 65 AC 23 (Target Slave 255, FC 06, Reg 255, Value 101, CRC)
Slave Response: FF 06 00 FF 00 65 AC 23 (Echo Response, then burns ID 101 and sets Reg 253=1 into EEPROM)
Master writes Mode 3 (Multi-Call Cycle) with Color 1 (Yellow = 4) and Color 2 (Red = 1) to Door LED Slave 20:
Write Mode (Reg 0 = 3): 14 06 00 00 00 03 C8 CF
Write Color 1 (Reg 1 = 4): 14 06 00 01 00 04 D9 0E
Write Color 2 (Reg 2 = 1): 14 06 00 02 00 01 E9 0E
Write Interval (Reg 10 = 1500ms): 14 06 00 0A 05 DC AC 2A