{
  "_comment": "DL205.json — DirectLOGIC DL205/DL260 quirk simulator. Models docs/v2/dl205.md as concrete register values. NOTE: pymodbus rejects unknown keys at device-list / setup level; explanatory comments live at top-level _comment + in README + git. Inline _quirk keys WITHIN individual register entries are accepted by pymodbus 3.13.0 (it only validates addr / value / action / parameters per entry). Each quirky uint16 is a pre-computed raw 16-bit value; pymodbus serves it verbatim. shared blocks=true matches DL series memory model. write list mirrors each seeded block — pymodbus rejects sweeping write ranges that include undefined cells.",

  "server_list": {
    "srv": {
      "comm": "tcp",
      "host": "0.0.0.0",
      "port": 5020,
      "framer": "socket",
      "device_id": 1
    }
  },

  "device_list": {
    "dev": {
      "setup": {
        "co size":    16384,
        "di size":     8192,
        "hr size":    16384,
        "ir size":     1024,
        "shared blocks": true,
        "type exception": false,
        "defaults": {
          "value":  {"bits": 0, "uint16": 0, "uint32": 0, "float32": 0.0, "string": " "},
          "action": {"bits": null, "uint16": null, "uint32": null, "float32": null, "string": null}
        }
      },
      "invalid": [],
      "write": [
        [0, 0],
        [200, 209],
        [1024, 1024],
        [1040, 1042],
        [1056, 1057],
        [1072, 1073],
        [1280, 1282],
        [1343, 1343],
        [1407, 1407],
        [1, 1],
        [128, 128],
        [192, 192],
        [250, 250],
        [8448, 8448]
      ],

      "uint16": [
        {"_quirk": "V0 marker. HR[0]=0xCAFE proves register 0 is valid on DL205/DL260 (rejects-register-0 was a DL05/DL06 relative-mode artefact). 0xCAFE = 51966.",
         "addr": 0,    "value": 51966},

        {"_quirk": "Scratch HR range 200..209 — mirrors the standard.json scratch range so the smoke test (DL205Profile.SmokeHoldingRegister=200) round-trips identically against either profile.",
         "addr": 200, "value": 0},
        {"addr": 201, "value": 0},
        {"addr": 202, "value": 0},
        {"addr": 203, "value": 0},
        {"addr": 204, "value": 0},
        {"addr": 205, "value": 0},
        {"addr": 206, "value": 0},
        {"addr": 207, "value": 0},
        {"addr": 208, "value": 0},
        {"addr": 209, "value": 0},

        {"_quirk": "V2000 marker. V2000 octal = decimal 1024 = PDU 0x0400. Marker 0x2000 = 8192.",
         "addr": 1024, "value": 8192},

        {"_quirk": "V40400 marker. V40400 octal = decimal 8448 = PDU 0x2100 (NOT register 0). Marker 0x4040 = 16448.",
         "addr": 8448, "value": 16448},

        {"_quirk": "String 'Hello' first char in LOW byte. HR[0x410] = 'H'(0x48) lo + 'e'(0x65) hi = 0x6548 = 25928.",
         "addr": 1040, "value": 25928},
        {"_quirk": "String 'Hello' second char-pair: 'l'(0x6C) lo + 'l'(0x6C) hi = 0x6C6C = 27756.",
         "addr": 1041, "value": 27756},
        {"_quirk": "String 'Hello' third char-pair: 'o'(0x6F) lo + null(0x00) hi = 0x006F = 111.",
         "addr": 1042, "value": 111},

        {"_quirk": "Float32 1.5f in CDAB word order. IEEE 754 1.5 = 0x3FC00000. CDAB = low word first: HR[0x420]=0x0000, HR[0x421]=0x3FC0=16320.",
         "addr": 1056, "value": 0},
        {"_quirk": "Float32 1.5f CDAB high word.",
         "addr": 1057, "value": 16320},

        {"_quirk": "BCD register. Decimal 1234 stored as BCD nibbles 0x1234 = 4660. NOT binary 1234 (= 0x04D2).",
         "addr": 1072, "value": 4660},
        {"_quirk": "High word of a 32-bit BCD pair at 1072/1073 (CDAB order: 1072=low, 1073=high). Seeded 0 = high BCD digits 0000, making the 32-bit value 0000_1234 = decimal 1234. Also present in write[] so proxy write tests can round-trip the 32-bit BCD pair.",
         "addr": 1073, "value": 0},

        {"_quirk": "FC03 cap test marker — first cell of a 128-register span the FC03 cap test reads. Other cells in the span aren't seeded explicitly, so reads of HR[1283..1342] / 1344..1406 return the default 0; the seeded markers at 1280, 1281, 1282, 1343, 1407 prove the span boundaries.",
         "addr": 1280, "value": 0},
        {"addr": 1281, "value": 1},
        {"addr": 1282, "value": 2},
        {"addr": 1343, "value": 63},
        {"addr": 1407, "value": 127}
      ],

      "bits": [
        {"_quirk": "X-input bank marker cell. X0 -> DI 0 conflicts with uint16 V0 at cell 0, so this marker covers X20 octal (= decimal 16 = DI 16 = cell 1 bit 0). X20=ON, X23 octal (DI 19 = cell 1 bit 3)=ON -> cell 1 value = 0b00001001 = 9.",
         "addr": 1, "value": 9},

        {"_quirk": "Y-output bank marker cell. pymodbus's simulator maps Modbus FC01/02/05 bit-addresses to cell index = bit_addr / 16; so Modbus coil 2048 lives at cell 128 bit 0. Y0=ON (bit 0), Y1=OFF (bit 1), Y2=ON (bit 2) -> value=0b00000101=5 proves DL260 mapping Y0 -> coil 2048.",
         "addr": 128, "value": 5},

        {"_quirk": "C-relay bank marker cell. Modbus coil 3072 -> cell 192 bit 0. C0=ON (bit 0), C1=OFF (bit 1), C2=ON (bit 2) -> value=5 proves DL260 mapping C0 -> coil 3072.",
         "addr": 192, "value": 5},

        {"_quirk": "Scratch cell for coil 4000..4015 write round-trip tests. Cell 250 holds Modbus coils 4000-4015; all bits start at 0 and tests set specific bits via FC05.",
         "addr": 250, "value": 0}
      ],

      "uint32":  [],
      "float32": [],
      "string":  [],
      "repeat":  []
    }
  }
}
