diff --git a/.editorconfig b/.editorconfig
index e620b1b..dc806e6 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,8 +11,8 @@ charset = utf-8
 trim_trailing_whitespace = true
 insert_final_newline = true
 
-[*.{py,yaml,yml}]
+[*.{py,yaml,yml,md}]
 indent_style = space
 
-[*.{yaml,yml}]
+[*.{yaml,yml,md}]
 indent_size = 2
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b820aa6..f4b6d51 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,6 +26,8 @@ repos:
     rev: 2.3.54
     hooks:
       - id: editorconfig-checker
+        args:
+          - "--exclude=Protocol.md"
 
   - repo: https://github.com/PyCQA/flake8
     rev: 4.0.1
@@ -38,7 +40,7 @@ repos:
       - id: mypy
 
   - repo: https://github.com/psf/black
-    rev: 21.9b0
+    rev: 21.10b0
     hooks:
       - id: black
 
diff --git a/Protocol.md b/Protocol.md
new file mode 100644
index 0000000..160f751
--- /dev/null
+++ b/Protocol.md
@@ -0,0 +1,85 @@
+# Protocol
+
+The protocol checksum is litle-endian CRC16-MODBUS, but the data itself seems to be big-endian (network order).
+It is structured around 16bit words (read 4 returns 8 bytes).
+
+I have seen the "Transfer ID?" field containing 0xFF and 0x01, I am not yet sure of the putpose of this field. Most transactions it is set to 0xFF.
+
+## Reading
+
+### Read request
+
+```text
+   ┌──────────────┐
+ ╔═╡ Transfer ID? │
+ ║ └──────────────┘
+ ║    ┌────────────────────┐
+ ║  ╔═╡ Operation (3=read) │
+ ║  ║ └────────────────────┘
+ ║  ║      ┌───────────────┐
+ ║  ║    ╔═╡ Start address │
+ ║  ║    ║ └───────────────┘
+ ║  ║    ║       ┌────────────────────────────────┐
+ ║  ║    ║     ╔═╡ Number of 2-byte words to read │
+ ║  ║    ║     ║ └────────────────────────────────┘
+ ║  ║    ║     ║       ┌─────────────────┐
+ ║  ║    ║     ║     ╔═╡ Transaction CRC │
+ ║  ║    ║     ║     ║ └─────────────────┘
+┌╨─┬╨─┬──╨──┬──╨──┬──╨──┐
+│FF│03│00 0C│00 08│91 d1│
+└──┴──┴─────┴─────┴─────┘
+```
+
+### Read response
+
+```text
+   ┌──────────────┐
+ ╔═╡ Transfer ID? │
+ ║ └──────────────┘
+ ║    ┌────────────────────┐
+ ║  ╔═╡ Operation (3=read) │
+ ║  ║ └────────────────────┘
+ ║  ║    ┌──────────────────────────┐
+ ║  ║  ╔═╡ Number of bytes returned │
+ ║  ║  ║ └──────────────────────────┘
+ ║  ║  ║    ┌──────┐                    ┌─────────────────┐
+ ║  ║  ║  ╔═╡ Data │                    │ Transaction CRC ╞═╗
+ ║  ║  ║  ║ └──────┘                    └─────────────────┘ ║
+┌╨─┬╨─┬╨─┬╨──────────────────────────────────────────────┬──╨──┐
+│FF│03│10│20 20 20 20 4D 4C 32 34 32 30 20 20 20 20 20 20│FD 17│
+└──┴──┴──┴───────────────────────────────────────────────┴─────┘
+```
+
+This particular memory section contains the device SKU: ML2420
+
+## Writing
+
+### Write request
+
+```text
+   ┌──────────────┐
+ ╔═╡ Transfer ID? │
+ ║ └──────────────┘
+ ║    ┌────────────────────┐
+ ║  ╔═╡ Operation (6=read) │
+ ║  ║ └────────────────────┘
+ ║  ║      ┌─────────┐
+ ║  ║    ╔═╡ Address │
+ ║  ║    ║ └─────────┘
+ ║  ║    ║       ┌──────┐
+ ║  ║    ║     ╔═╡ Data │
+ ║  ║    ║     ║ └──────┘
+ ║  ║    ║     ║       ┌─────────────────┐
+ ║  ║    ║     ║     ╔═╡ Transaction CRC │
+ ║  ║    ║     ║     ║ └─────────────────┘
+┌╨─┬╨─┬──╨──┬──╨──┬──╨──┐
+│FF│06│01 0A│00 01│7C 2A│
+└──┴──┴─────┴─────┴─────┘
+```
+
+The data at 0x010A is a boolean controlling the load output switch.
+
+### Write response
+
+Seems to return exactly the same as the data written,
+presumably to allow verifying that the data did indeed get written.
diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..f39ad8e
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,15 @@
+# SolarMPPT
+
+<!-- TODO: Come up with a better name -->
+
+Python library for interracting with the rather generic MPPT solar charge controller I got from the hardware store.
+
+- [Biltema 25-5077](https://www.biltema.no/bil---mc/elektrisk-anlegg/solcellspaneler/mppt-regulator-20-a-2000045547)
+
+The Android app suggested for the bluetooth interface is
+[SolarApp](https://play.google.com/store/apps/details?id=com.shuori.gfv2.guangfu) by srne
+(I'm not currently able to find the bluetooth bridge on Biltema's website?
+It's got BT-1 printed on the front, and is basically just a RS-232 to BTLE UART GATT)
+
+[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
+![example workflow](https://github.com/oddstr13/SolarMPPT/actions/workflows/pre-commit/badge.svg)
diff --git a/solar_ble.py b/solar_ble.py
index ac30fc7..6b98fab 100755
--- a/solar_ble.py
+++ b/solar_ble.py
@@ -15,24 +15,33 @@ INTERVAL = 15
 write_device = "0000ffd1-0000-1000-8000-00805f9b34fb"
 # read_device   = "0000fff1-0000-1000-8000-00805f9b34fb"
 
-
+# get(255, 12, 2)
+# "ff 03 00 0c 00 02"
 CMD_GET_1 = b"\xff\x03\x00\x0c\x00\x02"
 # > ff 03 04 20 20 20 20
 
+# get(255, 12, 8)
+# ff 03 00 0c 00 08
 CMD_GET_MODEL = b"\xff\x03\x00\x0c\x00\x08"
 # > ff 03 10 20 20 20 20 4d 4c 32 34 32 30 20 20 20 20 20 20
 # Device SKU: ML2420
 
+# get(255, 20, 4)
+# ff 03 00 14 00 04
 CMD_GET_VERSION = b"\xff\x03\x00\x14\x00\x04"
 # > ff 03 08 00 04 02 00 02 00 00 03
 #         CC ?? 11 22 33 ?? 44 55 66
 # Version: 4.2.0
 
+# get(255, 24, 3)
+# ff 03 00 18 00 03
 CMD_GET_SERIAL = b"\xff\x03\x00\x18\x00\x03"
 # > ff 03 06 3c 13 02 67 00 01
 #         CC 11 22 33 33 ?? ??
 # SN: 60-19-0615
 
+# get(255, 256, 7)
+# ff 03 01 00 00 07
 CMD_GET_BATTERY_STATE = b"\xff\x03\x01\x00\x00\x07"
 # > ff 03 0e 00 48 00 7e 00 1d 0e 0d 00 7e 00 1c 00 03
 #         CC 11 11 22 22 33 33 44 55 66 66 77 77 88 88
@@ -45,6 +54,8 @@ CMD_GET_BATTERY_STATE = b"\xff\x03\x01\x00\x00\x07"
 # 7: Load current: 0.28 A
 # 8: Load power: 3 W
 
+# get(255, 263, 4)
+# ff 03 01 07 00 04
 CMD_GET_PANEL_STATUS = b"\xff\x03\x01\x07\x00\x04"
 # > ff 03 08 00 c8 00 14 00 04 00 01
 #         CC 11 11 22 22 33 33 ?? ??
@@ -53,6 +64,21 @@ CMD_GET_PANEL_STATUS = b"\xff\x03\x01\x07\x00\x04"
 # 3: Panel power: 4 W
 # Charging status?
 
+# set(255, 266, 1 or 0)
+# ff 06 01 0a 00 01
+CMD_ENABLE_LOAD = b"\xff\x06\x01\x0a\x00\x01"
+CMD_DISABLE_LOAD = b"\xff\x06\x01\x0a\x00\x00"
+REG_LOAD_ENABLE = 0x010A
+
+# get(255, 267, 21)
+# ff 03 01 0b 00 15
+CMD_GET_LOAD_PARAMETERS = b"\xff\x03\x01\x0b\x00\x15"
+# > ff 03 2a 00 7c 00 7f 00 51 00 20 00 0a 00 03 00 00 00 00 00
+# > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# > 00 00 00 00 00
+
+# get(255, 288, 3)
+# ff 03 01 20 00 03
 CMD_GET_2 = b"\xff\x03\x01\x20\x00\x03"
 # > ff 03 06 80 02 00 00 00 00
 #         CC 11 22 33 33 33 33
@@ -60,6 +86,8 @@ CMD_GET_2 = b"\xff\x03\x01\x20\x00\x03"
 # 2: ?: 2
 # 3: ?: 0
 
+# get(255, 57345, 33)
+# ff 03 e0 01 00 21
 CMD_GET_BATTERY_PARAMETERS = b"\xff\x03\xe0\x01\x00\x21"
 # > ff 03 42 07 d0 00 c8 ff 0c 00 02 00 a0 00 9b 00 92 00 90 00
 # > 8a 00 84 00 7e 00 78 00 6f 00 6a 64 32 00 05 00 78 00 78 00
@@ -67,13 +95,8 @@ CMD_GET_BATTERY_PARAMETERS = b"\xff\x03\xe0\x01\x00\x21"
 # > 0f 00 05 00 05 00 04 01 00
 # 33 * uint16
 
-# (0xff, 267, 21)
-CMD_GET_LOAD_PARAMETERS = b"\xff\x03\x01\x0b\x00\x15"
-# > ff 03 2a 00 7c 00 7f 00 51 00 20 00 0a 00 03 00 00 00 00 00
-# > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-# > 00 00 00 00 00
-
-# 01 03 f000 000a
+# get(1, 61440, 10)
+# 01 03 f0 00 00 0a
 CMD_GET_HISTORICAL_TODAY = b"\x01\x03\xf0\x00\x00\x0a"
 CMD_GET_HISTORICAL_YESTERDAY = b"\x01\x03\xf0\x01\x00\x0a"
 CMD_GET_HISTORICAL_D2 = b"\x01\x03\xf0\x02\x00\x0a"
@@ -103,9 +126,7 @@ CMD_GET_HISTORICAL_D3 = b"\x01\x03\xf0\x03\x00\x0a"
 # production_power = 0 Wh
 # consumption_power = 0 Wh
 
-CMD_ENABLE_LOAD = b"\xff\x06\x01\x0a\x00\x01"
-CMD_DISABLE_LOAD = b"\xff\x06\x01\x0a\x00\x00"
-
+# ff 78 00 00 00 01
 CMD_ = b"\xff\x78\x00\x00\x00\x01"
 
 # CMD_GET_BATTERY_STATE = b'\xff\x03\x01\x00\x00\x07'