Siscall Pro Logo
SISCALL PRO
Hardware & Firmware Technical Specification • Modbus RTU over RS-485

1. RS-485 Physical & Modbus RTU Data Link Parameters

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).

2. Physical Button Layout & Numbering Standard

Buttons are indexed in standard reading order (Top-Left → Top-Right → Bottom-Left → Bottom-Right):

4-BUTTON WALL UNIT
BUTTON 1Top-Left (Bit 0/1)
BUTTON 2Top-Right (Bit 2/3)
BUTTON 3Bottom-Left (Bit 4/5)
BUTTON 4Bottom-Right (Bit 6/7)
🚽 TOILET_IN (Bit 12)
📞 AUX_IN (Bit 13)
⚡ GND

Numbering for Other Models:

  • 1-Button Unit: Single center button = Button 1 (Bit 0/1).
  • 2-Button Unit: Top = Button 1, Bottom = Button 2.
  • 6-Button Unit: Row 1: B1, B2 | Row 2: B3, B4 | Row 3: B5, B6.
  • 8-Button Unit: Row 1: B1, B2 | Row 2: B3, B4 | Row 3: B5, B6 | Row 4: B7, B8.
  • Attached Toilet Unit: Connected to screw terminal TOILET_IN. Contact closed to GND triggers Bit 12 = 1.

3. Digital 7-Color RGB Truth Table (Codes 0 to 7)

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

4. Wall Unit Modbus Holding Register Reference

Modbus Function Codes:
FC 03 (`0x03`): Read Holding Registers
FC 06 (`0x06`): Write Single Holding Register
FC 16 (`0x10`): Write Multiple Holding Registers

A. Real-Time Inputs & Status (Read Only)

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

B. Configuration & Button RGB Color Registers (Saved in Non-Volatile EEPROM)

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).
400210x001420R/WEEPROMButton 1 Single-Press Color4 (Yellow)Color code triggered when Button 1 is single-pressed.
400220x001521R/WEEPROMButton 1 Long-Press Color1 (Red)Color code triggered when Button 1 is long-pressed.
400230x001622R/WEEPROMButton 2 Single-Press Color6 (Purple)Color code triggered when Button 2 is single-pressed.
400240x001723R/WEEPROMButton 2 Long-Press Color1 (Red)Color code triggered when Button 2 is long-pressed.
400250x001824R/WEEPROMButton 3 Single-Press Color3 (Blue)Color code triggered when Button 3 is single-pressed.
400260x001925R/WEEPROMButton 3 Long-Press Color1 (Red)Color code triggered when Button 3 is long-pressed.
400270x001A26R/WEEPROMButton 4 Single-Press Color2 (Green)Color code triggered when Button 4 is single-pressed.
400280x001B27R/WEEPROMButton 4 Long-Press Color0 (OFF)Long-press action on Button 4 (e.g. Care Reset).
400290x001C28R/WEEPROMAttached Toilet Trigger Color4 (Yellow)Color code triggered when Toilet cord is pulled.
400300x001D29R/WEEPROMAttached Handset Trigger Color4 (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 Bus
0x0000: 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.

5. Corridor Over-Door Dome LED (Ward Room Light — Up to 6 Active Calls)

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)
400020x00011R/WColor 1 (Bed 1)Color code (0 to 7) for Bed 1 active call
400030x00022R/WColor 2 (Bed 2)Color code (0 to 7) for Bed 2 active call
400040x00033R/WColor 3 (Bed 3)Color code (0 to 7) for Bed 3 active call
400050x00044R/WColor 4 (Bed 4)Color code (0 to 7) for Bed 4 active call
400060x00055R/WColor 5 (Bed 5)Color code for Bed 5 call (6-bed ward)
400070x00066R/WColor 6 (Bed 6)Color code for Bed 6 call (6-bed ward)
400110x000A10R/WCycle Time (ms)Time to display each color before alternating (Default: 1500ms)
400120x000B11R/WIdle Heartbeat ColorColor shown when all calls cleared (3=Blue, 0=OFF)
402560x00FF255R/WSlave IDModbus Slave ID (1..247). Saved in EEPROM.

6. Detailed Discovery Mode & Zero-DIP-Switch Slave ID Assignment Specification

Protocol Rule: Both regular runtime communication AND discovery mode use the EXACT SAME standard Modbus RTU protocol (19200 baud, 8-N-1, Function Codes FC 03 and FC 06). No special baud rate switches or proprietary protocols are required.

A. The Two Discovery Modes (Handling Factory-Tested Devices with Duplicate IDs)

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:

Option 1: Discover New / Pending Only (`0x00AA`)

Only units with Reg 253 == 0 (uncommissioned) will blink. Existing commissioned units ignore the broadcast, ensuring active hospital rooms are not disturbed.

Option 2: Force Discovery on ALL Units (`0x00FF`)

Every unit on the bus blinks regardless of previous state. Used for new ward installations or full re-addressing.

1
Admin Triggers Discovery from Gateway UI

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)
Microcontroller Action: Target units receive this broadcast and start flashing all button LEDs rapidly at 2.5 Hz (200ms ON / 200ms OFF). Slaves DO NOT reply on RS-485 to broadcast address 0 (0% bus collision).
2
Technician Physically Selects the Target Bed

The technician walks over to the specific bed (e.g. Bed 101) and presses and holds Button 1 (Top-Left) for 3 seconds.

Microcontroller Action: That specific wall unit detects the 3-second hold on Button 1. It immediately:
  • Stops flashing other LEDs and turns Button 1 SOLID YELLOW/BLUE.
  • Sets its internal live RAM Register 0 = `0x00AA` (Flag indicating: "I am physically selected for pairing!").
3
Gateway Reads the Selected Unit

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!)
4
Gateway Assigns the New Slave ID (e.g. ID 101)

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)
5
Microcontroller Burns ID to EEPROM & Sets Commissioned Flag
Microcontroller Execution:
  1. Saves value 101 into internal non-volatile EEPROM memory.
  2. Sets `Commissioned Flag (Reg 253) = 1` in EEPROM.
  3. Turns ALL BUTTON LEDs SOLID GREEN for 3.0 Seconds and emits a 200ms acoustic beep.
  4. Switches its active Modbus RS-485 listening address to `101`.
  5. Sets is_discovery_mode = false.
6
Gateway Pushes Full Configuration to Slave 101

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.

B. Complete Microcontroller Discovery State Machine (C Code)

// =========================================================================
// 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();
        }
    }
}

7. Summary: Exactly What Registers & Values Each Wall Unit Stores in EEPROM

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.
Total EEPROM Size Needed: Only 21 Bytes of internal EEPROM/Flash storage per microcontroller!

8. Microcontroller Firmware Boilerplate (C / C++ Full Reference)

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]);
        }
    }
}

9. Concrete Modbus RTU Hex Packet Examples

Example 1: Master Polls Wall Unit Status (Read Reg 0 on Slave ID 1)

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)

Example 2: Master Broadcasts Discovery Mode (Reg 254 = 0x00AA or 0x00FF)

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)

Example 3: Master Assigns Slave ID 101 (Reg 255 = 101)

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)

Example 4: Master Sets Corridor Door Light to Alternating Cycle Mode

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