GE Medical Flashpad Digital Xray Detector: Difference between revisions

Technical Specifications: linking to shock event log
Line 10: Line 10:
{{Note|[[Artificial intelligence|AI]] assistance was used in writing this page for improved formatting and readability, as well as in the process of finding information, testing, and analyzing firmware dumps and backups.}}
{{Note|[[Artificial intelligence|AI]] assistance was used in writing this page for improved formatting and readability, as well as in the process of finding information, testing, and analyzing firmware dumps and backups.}}


== Purpose and Motivation ==
==Purpose and Motivation==


This project documents the reverse engineering of the GE FlashPad wireless
This project documents the reverse engineering of the GE FlashPad wireless
Line 26: Line 26:
The intended beneficiaries are:
The intended beneficiaries are:


* Hobbyists, researchers, and engineers who want a high quality flat panel detector for their own imaging projects.
*Hobbyists, researchers, and engineers who want a high quality flat panel detector for their own imaging projects.
* Veterinary practices, which can put surplus human grade detectors to good use at a fraction of the cost of new equipment.
*Veterinary practices, which can put surplus human grade detectors to good use at a fraction of the cost of new equipment.
* Clinics and hospitals in countries and regions where a complete commercial system is unaffordable, allowing serviceable detectors to keep providing diagnostic imaging instead of being scrapped.
*Clinics and hospitals in countries and regions where a complete commercial system is unaffordable, allowing serviceable detectors to keep providing diagnostic imaging instead of being scrapped.
 
[[File:Xray current clamp multimeter.png|thumb|xray of a current clamp multimeter]]
[[File:Xray current clamp multimeter.png|thumb|xray of a current clamp multimeter]]
This is done for human good. Every detector returned to service is one less
This is done for human good. Every detector returned to service is one less
Line 41: Line 42:
[[File:Ge flashpad tether cable pinout diagram.png|thumb|Pinout Diagram of the Tether cable]]
[[File:Ge flashpad tether cable pinout diagram.png|thumb|Pinout Diagram of the Tether cable]]
[[File:Ge flashpad tether wiring for ethernet cable.jpg|thumb|Professional Tether wiring to attach a Ethernet Cable and 12V socket to it.]]
[[File:Ge flashpad tether wiring for ethernet cable.jpg|thumb|Professional Tether wiring to attach a Ethernet Cable and 12V socket to it.]]
The Flashpad uses a '''~40 × 40 cm CsI scintillator''' bonded to a [[Thin-film transistor|TFT]] photodetector array mounted on glass. The assembly is highly sensitive to shock and impact damage.
The Flashpad uses a '''~40 × 40 cm CsI scintillator''' bonded to a [[Thin-film transistor|TFT]] photodetector array mounted on glass. The assembly is highly sensitive to shock and impact damage. See section [[#Reading the Drop and Shock Event Log|drop and shock event log]]


{| class="wikitable"
{| class="wikitable"
Line 62: Line 63:
The theoretical 5 lp/mm spatial resolution is primarily limited in practice by the focal spot size of the X-ray source. Use of an anti-scatter grid can improve effective resolution.
The theoretical 5 lp/mm spatial resolution is primarily limited in practice by the focal spot size of the X-ray source. Use of an anti-scatter grid can improve effective resolution.


=== Status of Reverse Engineering ===
===Status of Reverse Engineering===


{| class="wikitable"
{| class="wikitable"
|-
|-
! What !! Status
!What!!Status
|-
|-
| Connect, beacon, ACK || Works
|Connect, beacon, ACK||Works
|-
|-
| PORT_SETUP || Works
|PORT_SETUP||Works
|-
|-
| SIGNATURE_REQUEST / serial number readout || Works
|SIGNATURE_REQUEST / serial number readout||Works
|-
|-
| Script download (Scripts 7, 8, 1) || Works
|Script download (Scripts 7, 8, 1)||Works
|-
|-
| EXECUTE_SCRIPT || Works
|EXECUTE_SCRIPT||Works
|-
|-
| EXECUTION_COMPLETE (dark acquisition) || Works
|EXECUTION_COMPLETE (dark acquisition)||Works
|-
|-
| EXECUTION_COMPLETE (standard acquisition) || Needs real X-ray trigger to test
|EXECUTION_COMPLETE (standard acquisition)||Needs real X-ray trigger to test
|-
|-
| Image data on port 6660 || Does not work yet, under investigation. Will not send Imagedata yet.
|Image data on port 6660||Does not work yet, under investigation. Will not send Imagedata yet.
|}
|}


Line 98: Line 99:




== Communication Protocol ==
==Communication Protocol==


This section documents the URP/PDAP protocol used by the GE Flashpad (codename '''Apollo''') to communicate with a host over Ethernet. All findings are based on live capture tests, configuration files, and reverse-engineering of the GE SuperBee software stack.
This section documents the URP/PDAP protocol used by the GE Flashpad (codename '''Apollo''') to communicate with a host over Ethernet. All findings are based on live capture tests, configuration files, and reverse-engineering of the GE SuperBee software stack.
Line 104: Line 105:
{{Note|All findings are based on a single unit and may not be fully accurate.}}
{{Note|All findings are based on a single unit and may not be fully accurate.}}


=== Network Setup ===
===Network Setup===


All findings were over Ethernet only, no UWB or WIFI has been used.  
All findings were over Ethernet only, no UWB or WIFI has been used.  
Line 115: Line 116:
{| class="wikitable"
{| class="wikitable"
|-
|-
! Role !! IP !! Port !! Direction
!Role!!IP!!Port!!Direction
|-
|-
| All commands: host -> detector || 192.168.1.30 || '''8100''' (UDP) || Host sends here
|All commands: host -> detector||192.168.1.30||'''8100''' (UDP)||Host sends here
|-
|-
| Discovery beacons: detector -> host || - || '''4500''' (UDP) || Detector sends here initially
|Discovery beacons: detector -> host||-||'''4500''' (UDP)||Detector sends here initially
|-
|-
| Protocol replies: detector -> host || - || '''5550''' (UDP) || Detector sends here after setup
|Protocol replies: detector -> host||-||'''5550''' (UDP)||Detector sends here after setup
|-
|-
| Image pixel data: detector -> host || - || '''6660''' (UDP) || Detector streams frames here
|Image pixel data: detector -> host||-||'''6660''' (UDP)||Detector streams frames here
|}
|}


In practice you can listen on port '''5550''' for everything (beacons and replies) by advertising that port in both <code>SYSTEM_STARTUP</code> and <code>PORT_SETUP</code>. The detector sends to whichever port was most recently configured.
In practice you can listen on port '''5550''' for everything (beacons and replies) by advertising that port in both <code>SYSTEM_STARTUP</code> and <code>PORT_SETUP</code>. The detector sends to whichever port was most recently configured.


=== Protocol Layers ===
===Protocol Layers===


Two layers, carried over UDP:
Two layers, carried over UDP:


; URP (Unified Registration Protocol)
;URP (Unified Registration Protocol)
: 8-byte wrapper on every packet. Handles sequencing and acknowledgement.
:8-byte wrapper on every packet. Handles sequencing and acknowledgement.


; PDAP (Proprietary Detector Access Protocol)
;PDAP (Proprietary Detector Access Protocol)
: The actual command layer, present inside URP packets when <code>CmdFlag = 0</code>.
:The actual command layer, present inside URP packets when <code>CmdFlag = 0</code>.


Every UDP packet starts with a URP header:
Every UDP packet starts with a URP header:
Line 144: Line 145:
</pre>
</pre>


* <code>CmdFlag = 0</code> -- data packet, PDAP command follows.
*<code>CmdFlag = 0</code> -- data packet, PDAP command follows.
* <code>CmdFlag = 1</code> -- bare ACK, no PDAP body. SeqId echoes the packet being acknowledged.
*<code>CmdFlag = 1</code> -- bare ACK, no PDAP body. SeqId echoes the packet being acknowledged.


Both sides must ACK every data packet immediately. The detector silently drops packets with a SeqId it has already seen, so always increment SeqId for each new command.
Both sides must ACK every data packet immediately. The detector silently drops packets with a SeqId it has already seen, so always increment SeqId for each new command.
Line 155: Line 156:
</pre>
</pre>


=== Connecting to the Detector ===
===Connecting to the Detector===


The connection sequence is:
The connection sequence is:


# Broadcast <code>SYSTEM_STARTUP</code> to tell the detector where to reply.
#Broadcast <code>SYSTEM_STARTUP</code> to tell the detector where to reply.
# The detector sends a <code>BEACON</code> back -- ACK it and sync your sequence counter.
#The detector sends a <code>BEACON</code> back -- ACK it and sync your sequence counter.
# Send <code>PORT_SETUP</code> to configure the reply and image ports.
#Send <code>PORT_SETUP</code> to configure the reply and image ports.
# Send <code>SIGNATURE_REQUEST</code> to read the detector identity (serial number, model, firmware, MAC).
#Send <code>SIGNATURE_REQUEST</code> to read the detector identity (serial number, model, firmware, MAC).


==== Step 1: SYSTEM_STARTUP ====
====Step 1: SYSTEM_STARTUP====


Broadcast UDP to <code>192.168.1.255:8100</code>. Always uses <code>SeqId = 0</code>.
Broadcast UDP to <code>192.168.1.255:8100</code>. Always uses <code>SeqId = 0</code>.
Line 196: Line 197:
</syntaxhighlight>
</syntaxhighlight>


==== Step 2: Receiving the BEACON and ACKing ====
====Step 2: Receiving the BEACON and ACKing====


The detector broadcasts a <code>BEACON</code> (cmd_type=1) roughly every 2 seconds. After sending SYSTEM_STARTUP you should get one quickly. Parse the detector SeqId from the URP header and ACK it:
The detector broadcasts a <code>BEACON</code> (cmd_type=1) roughly every 2 seconds. After sending SYSTEM_STARTUP you should get one quickly. Parse the detector SeqId from the URP header and ACK it:
Line 212: Line 213:
</syntaxhighlight>
</syntaxhighlight>


==== Step 3: PORT_SETUP ====
====Step 3: PORT_SETUP====


Tells the detector which host ports to use for replies and image data.
Tells the detector which host ports to use for replies and image data.
Line 230: Line 231:
</syntaxhighlight>
</syntaxhighlight>


==== Step 4: Reading the Serial Number (SIGNATURE_REQUEST) ====
====Step 4: Reading the Serial Number (SIGNATURE_REQUEST)====


Empty command, the detector replies with a 54-byte payload containing its identity.
Empty command, the detector replies with a 54-byte payload containing its identity.
Line 263: Line 264:
</pre>
</pre>


=== Running an Acquisition ===
===Running an Acquisition===


After the connection sequence above, download scripts to the detector and then execute them.
After the connection sequence above, download scripts to the detector and then execute them.


==== ROE Initialisation (Script 7) ====
====ROE Initialisation (Script 7)====


Always run this first. It initialises the readout electronics and takes about 4-5 seconds. The detector sends host event ID 17 when done.
Always run this first. It initialises the readout electronics and takes about 4-5 seconds. The detector sends host event ID 17 when done.


==== Dark / Offset Acquisition (Script 1) ====
====Dark / Offset Acquisition (Script 1)====


No X-ray source required. Runs a dark-field exposure for offset calibration. Use this to verify the acquisition pipeline without a generator.
No X-ray source required. Runs a dark-field exposure for offset calibration. Use this to verify the acquisition pipeline without a generator.


==== Standard Acquisition (Script 0) ====
====Standard Acquisition (Script 0)====


Requires an actual X-ray exposure. <code>EXECUTION_COMPLETE</code> will '''not''' arrive without a real X-ray trigger.
Requires an actual X-ray exposure. <code>EXECUTION_COMPLETE</code> will '''not''' arrive without a real X-ray trigger.


==== Sequence Overview ====
====Sequence Overview====


<pre>
<pre>
Line 318: Line 319:
</pre>
</pre>


=== Sequence Counter Rules ===
===Sequence Counter Rules===


* <code>SYSTEM_STARTUP</code> always uses <code>SeqId = 0</code>.
*<code>SYSTEM_STARTUP</code> always uses <code>SeqId = 0</code>.
* After the first beacon, set host SeqId to beacon_SeqId + 1.
*After the first beacon, set host SeqId to beacon_SeqId + 1.
* Increment SeqId by 1 for every new data packet (CmdFlag=0).
*Increment SeqId by 1 for every new data packet (CmdFlag=0).
* Bare ACKs echo the SeqId of the packet being acknowledged and do not consume a SeqId.
*Bare ACKs echo the SeqId of the packet being acknowledged and do not consume a SeqId.
* The detector silently drops any packet with a SeqId it has already processed, so never reuse one.
*The detector silently drops any packet with a SeqId it has already processed, so never reuse one.




 
==Sensor Readout and Host Registration==
== Sensor Readout and Host Registration ==


This section documents the reverse engineered sensor telemetry interface and the
This section documents the reverse engineered sensor telemetry interface and the
Line 335: Line 335:
the detector at port 8100; replies return to the host command port.
the detector at port 8100; replies return to the host command port.


=== Sensor Readout ===
===Sensor Readout===


The detector exposes an analog sensor interface (the DEM, Detector Environment
The detector exposes an analog sensor interface (the DEM, Detector Environment
Line 341: Line 341:
acquisition state.
acquisition state.


==== Commands ====
====Commands====


{| class="wikitable"
{| class="wikitable"
! cmd_type !! Meaning !! Request payload !! Reply payload
!cmd_type!!Meaning!!Request payload!!Reply payload
|-
|-
| 0x7900 || Raw sensor read || [sensorId:4 LE] || [value:4 LE] (12 bit ADC count)
|0x7900||Raw sensor read||[sensorId:4 LE]||[value:4 LE] (12 bit ADC count)
|-
|-
| 0x7902 || Converted sensor read || [sensorId:4 LE] || [value:4 LE] (engineering units, signed)
|0x7902||Converted sensor read||[sensorId:4 LE]||[value:4 LE] (engineering units, signed)
|-
|-
| 0x7904 || Detailed / radio || [selector:4 LE] || [value:4 LE]
|0x7904||Detailed / radio||[selector:4 LE]||[value:4 LE]
|}
|}


Line 363: Line 363:
Registration section for the read protocol).
Registration section for the read protocol).


==== Power rails (live readings) ====
====Power rails (live readings)====


All supply rails read correctly via 0x7902 and are within normal range for a
All supply rails read correctly via 0x7902 and are within normal range for a
Line 369: Line 369:


{| class="wikitable"
{| class="wikitable"
! Sensor !! sensorId !! Converted !! Value
!Sensor!!sensorId!!Converted!!Value
|-
|-
| DCIN_RAW || 10 || 12100 mV || +12.10 V (main DC input)
|DCIN_RAW||10||12100 mV||+12.10 V (main DC input)
|-
|-
| LCORE_UNREG || 11 || 1724 mV || +1.72 V
|LCORE_UNREG||11||1724 mV||+1.72 V
|-
|-
| LPANA_UNREG || 12 || 5776 mV || +5.78 V
|LPANA_UNREG||12||5776 mV||+5.78 V
|-
|-
| LNANA_UNREG || 13 || -5801 mV || -5.80 V
|LNANA_UNREG||13||-5801 mV||-5.80 V
|-
|-
| SCAN_VCC || 14 || 5086 mV || +5.09 V (gate driver)
|SCAN_VCC||14||5086 mV||+5.09 V (gate driver)
|-
|-
| P5V_REF || 16 || 5025 mV || +5.03 V (5 V reference)
|P5V_REF||16||5025 mV||+5.03 V (5 V reference)
|-
|-
| V_ON || 17 || 11085 mV || +11.09 V (TFT gate on)
|V_ON||17||11085 mV||+11.09 V (TFT gate on)
|-
|-
| V_OFF || 18 || -12378 mV || -12.38 V (TFT gate off)
|V_OFF||18||-12378 mV||-12.38 V (TFT gate off)
|-
|-
| V_COMMON || 19 || -9385 mV || -9.39 V
|V_COMMON||19||-9385 mV||-9.39 V
|-
|-
| 3V3 || 29 || 3177 mV || +3.18 V (3.3 V logic)
|3V3||29||3177 mV||+3.18 V (3.3 V logic)
|-
|-
| VCC_UNREG || 37 || 3399 mV || +3.40 V
|VCC_UNREG||37||3399 mV||+3.40 V
|-
|-
| PARCPREG || 38 || 3768 mV || +3.77 V (ARC preamp +)
|PARCPREG||38||3768 mV||+3.77 V (ARC preamp +)
|-
|-
| NARCPREG || 39 || -3732 mV || -3.73 V (ARC preamp -)
|NARCPREG||39||-3732 mV||-3.73 V (ARC preamp -)
|-
|-
| PANA_UNREG || 45 || 18352 mV || +18.35 V (photodiode bias +)
|PANA_UNREG||45||18352 mV||+18.35 V (photodiode bias +)
|-
|-
| NANA_UNREG || 46 || -19251 mV || -19.25 V (photodiode bias -)
|NANA_UNREG||46||-19251 mV||-19.25 V (photodiode bias -)
|}
|}


Line 405: Line 405:
P5VA_SW, N5VA_SW, FGATE_NVC_L, FGATE_PVC_L, etc.) read at or near zero.
P5VA_SW, N5VA_SW, FGATE_NVC_L, FGATE_PVC_L, etc.) read at or near zero.


==== Known limitations ====
====Known limitations====


* '''Temperatures''' (Temp_Surface, sensorId 336; Temp_Panel, sensorId 352): the raw 0x7900 read rails at 0x3FF (1023, the ADC maximum), indicating an open thermistor path while the panel is idle. This is a hardware/state condition, not a command problem, and the temperature is not readable from the host in this state.
*'''Temperatures''' (Temp_Surface, sensorId 336; Temp_Panel, sensorId 352): the raw 0x7900 read rails at 0x3FF (1023, the ADC maximum), indicating an open thermistor path while the panel is idle. This is a hardware/state condition, not a command problem, and the temperature is not readable from the host in this state.
* '''Unimplemented sensors''': sensorIds 70 (Accelerator), 78 (Gravity), and 256 to 259 (Battery status, name, life, capacity), and 272 (Grid status) are not implemented on this DEM. The detector returns the leftover conversion register contents (a duplicate of a previously read sensor) rather than a real value, so these rows must be discarded.
*'''Unimplemented sensors''': sensorIds 70 (Accelerator), 78 (Gravity), and 256 to 259 (Battery status, name, life, capacity), and 272 (Grid status) are not implemented on this DEM. The detector returns the leftover conversion register contents (a duplicate of a previously read sensor) rather than a real value, so these rows must be discarded.
* '''Accelerometer''': functional through a separate addressing scheme using raw cmd 0x7900 with selectors 0x42 (X), 0x43 (Y), 0x44 (Z), returning 12 bit per axis counts.
*'''Accelerometer''': functional through a separate addressing scheme using raw cmd 0x7900 with selectors 0x42 (X), 0x43 (Y), 0x44 (Z), returning 12 bit per axis counts.


=== Host Registration (Pairing) ===
===Host Registration (Pairing)===


URP stands for Unified Registration Protocol. The detector maintains a host
URP stands for Unified Registration Protocol. The detector maintains a host
Line 417: Line 417:
primary host, so registration is a prerequisite for image transfer.
primary host, so registration is a prerequisite for image transfer.


==== Host identity (MAC and HostId) ====
====Host identity (MAC and HostId)====


Each host is identified by a 16 character HostId derived deterministically from
Each host is identified by a 16 character HostId derived deterministically from
Line 423: Line 423:
script) is:
script) is:


# Take the eth0 MAC, remove the colon separators, convert to upper case (12 hex characters).
#Take the eth0 MAC, remove the colon separators, convert to upper case (12 hex characters).
# Prepend the last 4 characters to the full 12 characters.
#Prepend the last 4 characters to the full 12 characters.
# The result is 16 hex characters.
#The result is 16 hex characters.


Example: MAC 00:6f:00:01:0a:3a becomes 006F00010A3A, then the last four (0A3A)
Example: MAC 00:6f:00:01:0a:3a becomes 006F00010A3A, then the last four (0A3A)
are prepended, giving HostId 0A3A006F00010A3A.
are prepended, giving HostId 0A3A006F00010A3A.


==== HostList structure ====
====HostList structure====


The host list is stored in flash at offset 0x940000 and can be read back over
The host list is stored in flash at offset 0x940000 and can be read back over
Line 448: Line 448:
  ...      4    CRC (big endian; see below)
  ...      4    CRC (big endian; see below)


==== HostList from the unit under test ====
====HostList from the unit under test====


Detector: MAC 40:F4:A0:00:78:4D, serial UA45829-7, model 5340000-7,
Detector: MAC 40:F4:A0:00:78:4D, serial UA45829-7, model 5340000-7,
Line 455: Line 455:


{| class="wikitable"
{| class="wikitable"
! Index !! HostId !! Derived MAC !! Name
!Index!!HostId!!Derived MAC!!Name
|-
|-
| 0 || 2C6400045FB42C64 || 00:04:5F:B4:2C:64 || Haus 207 / ITS
|0||2C6400045FB42C64||00:04:5F:B4:2C:64||Haus 207 / ITS
|-
|-
| 1 || B044E8393512B044 || E8:39:35:12:B0:44 || Not Initialized
|1||B044E8393512B044||E8:39:35:12:B0:44||Not Initialized
|-
|-
| 2 || 5CF800045FB15CF8 || 00:04:5F:B1:5C:F8 || Not_Initialized
|2||5CF800045FB15CF8||00:04:5F:B1:5C:F8||Not_Initialized
|}
|}


Line 467: Line 467:
deployment, but no primary host is currently designated.
deployment, but no primary host is currently designated.


==== Checksum (CRC) ====
====Checksum (CRC)====


The HostList (and other flash data blobs) are protected by a 4 byte trailing
The HostList (and other flash data blobs) are protected by a 4 byte trailing
CRC. Parameters:
CRC. Parameters:


* Polynomial: 0x04C11DB7
*Polynomial: 0x04C11DB7
* Initial value: 0
*Initial value: 0
* MSB first, augmented message style (the data bit is shifted into the LSB; no input or output reflection; no final XOR)
*MSB first, augmented message style (the data bit is shifted into the LSB; no input or output reflection; no final XOR)
* Stored big endian
*Stored big endian


To generate: compute the CRC over the data followed by four zero bytes, then
To generate: compute the CRC over the data followed by four zero bytes, then
Line 492: Line 492:
  # trailer = crc(data + b"\x00\x00\x00\x00"), stored big endian
  # trailer = crc(data + b"\x00\x00\x00\x00"), stored big endian


==== Read and write transport ====
====Read and write transport====


Data blobs (including the HostList) are moved with a configure / buffer /
Data blobs (including the HostList) are moved with a configure / buffer /
Line 500: Line 500:


{| class="wikitable"
{| class="wikitable"
! Step !! cmd_type !! host to detector !! detector to host
!Step!!cmd_type!!host to detector!!detector to host
|-
|-
| Configure || 0x13 || [uploadId:4 LE] || [status:1][totalSize:4 LE]
|Configure||0x13||[uploadId:4 LE]||[status:1][totalSize:4 LE]
|-
|-
| Buffer || 0x14 || [bufId:4 LE][numBytes:4 LE] || [bufId:4 LE][numBytes:4 LE][data]
|Buffer||0x14||[bufId:4 LE][numBytes:4 LE]||[bufId:4 LE][numBytes:4 LE][data]
|}
|}


Line 510: Line 510:


{| class="wikitable"
{| class="wikitable"
! Step !! cmd_type !! host to detector !! detector to host
!Step!!cmd_type!!host to detector!!detector to host
|-
|-
| Configure || 0x0E || [downloadId:4 LE][totalSize:4 LE] || [status:1]
|Configure||0x0E||[downloadId:4 LE][totalSize:4 LE]||[status:1]
|-
|-
| Buffer || 0x0F || [bufId:4 LE][numBytes:4 LE][data] || [status:1][reserved:4]
|Buffer||0x0F||[bufId:4 LE][numBytes:4 LE][data]||[status:1][reserved:4]
|-
|-
| Commit || 0x10 || (empty) || [status:1]
|Commit||0x10||(empty)||[status:1]
|}
|}


Line 523: Line 523:
download can corrupt flash; the operation is irreversible on this hardware.
download can corrupt flash; the operation is irreversible on this hardware.


==== Registering a new host ====
====Registering a new host====


To register a host and make it the image destination, read the current HostList
To register a host and make it the image destination, read the current HostList
Line 531: Line 531:
(0x0E / 0x0F / 0x10).
(0x0E / 0x0F / 0x10).


== Reading the Drop and Shock Event Log ==
==Reading the Drop and Shock Event Log==


The detector contains an accelerometer based shock watchdog that records drop
The detector contains an accelerometer based shock watchdog that records drop
Line 539: Line 539:
in the small onboard EEPROM on the detector PCB.
in the small onboard EEPROM on the detector PCB.


=== How to read it ===
===How to read it===


The shock log is exposed as data category 0x72 on the upload (read) interface.
The shock log is exposed as data category 0x72 on the upload (read) interface.
Line 550: Line 550:
(32 KB I2C part) for anyone reading the hardware directly.
(32 KB I2C part) for anyone reading the hardware directly.


=== Example output ===
===Example output===


The following is the actual log read from detector serial UA45829-7. The file
The following is the actual log read from detector serial UA45829-7. The file
Line 589: Line 589:
         157804584600183,  149266438700135 }
         157804584600183,  149266438700135 }


=== Interpreting the records ===
===Interpreting the records===


The record key encodes the event time and the peak axis values (an epoch style
The record key encodes the event time and the peak axis values (an epoch style
Line 601: Line 601:


{| class="wikitable"
{| class="wikitable"
! Date and time !! VibrationX !! VibrationY !! VibrationZ
!Date and time!!VibrationX!!VibrationY!!VibrationZ
|-
|-
| 2017-04-20 06:59:47 || 0 || 0 || 135
|2017-04-20 06:59:47||0||0||135
|-
|-
| 2020-01-03 11:04:06 || 0 || 0 || 183
|2020-01-03 11:04:06||0||0||183
|-
|-
| 2020-06-14 07:52:04 || -172 || 0 || -113
|2020-06-14 07:52:04||-172||0||-113
|-
|-
| 2020-11-13 05:40:30 || 0 || 0 || 170
|2020-11-13 05:40:30||0||0||170
|-
|-
| 2020-12-17 06:11:45 || 0 || 0 || -101
|2020-12-17 06:11:45||0||0||-101
|-
|-
| 2021-11-07 07:03:55 || 0 || 0 || -123
|2021-11-07 07:03:55||0||0||-123
|-
|-
| 2022-01-27 06:21:30 || -132 || 0 || -119
|2022-01-27 06:21:30||-132||0||-119
|}
|}


=== Reading the summary fields ===
===Reading the summary fields===


{| class="wikitable"
{| class="wikitable"
! Field !! Meaning
!Field!!Meaning
|-
|-
| LastKnownGoodTime || Timestamp of the last successful self check (here 2024-04-04), the most recent point at which the detector was known to be operating normally
|LastKnownGoodTime||Timestamp of the last successful self check (here 2024-04-04), the most recent point at which the detector was known to be operating normally
|-
|-
| NumberOfL3Events || Count of lower severity (L3) shock events; zero on this unit
|NumberOfL3Events||Count of lower severity (L3) shock events; zero on this unit
|-
|-
| NumberOfL5Events || Count of high severity (L5) shock events; seven on this unit, matching the seven records above
|NumberOfL5Events||Count of high severity (L5) shock events; seven on this unit, matching the seven records above
|-
|-
| ShockDataTimeList || Index of all stored event keys, newest first
|ShockDataTimeList||Index of all stored event keys, newest first
|}
|}


Line 635: Line 635:
of field use and last reported a good self check in April 2024.
of field use and last reported a good self check in April 2024.


== FlashPad Detector: Internal Flash Dump and Data Files ==
==FlashPad Detector: Internal Flash Dump and Data Files==


This section documents how the full contents of the detector's internal flash
This section documents how the full contents of the detector's internal flash
Line 642: Line 642:
serial UA45829-7, MAC 40:F4:A0:00:78:4D, firmware 1.6.0.4.2.0.1.3).
serial UA45829-7, MAC 40:F4:A0:00:78:4D, firmware 1.6.0.4.2.0.1.3).


=== Background ===
===Background===


The detector's main storage is a Spansion/Cypress S29GL512P (marked
The detector's main storage is a Spansion/Cypress S29GL512P (marked
Line 651: Line 651:
complete, byte exact dump possible over UDP with no physical access.
complete, byte exact dump possible over UDP with no physical access.


=== Extraction method ===
===Extraction method===


The upload interface is the read counterpart of the firmware download path and
The upload interface is the read counterpart of the firmware download path and
Line 658: Line 658:


{| class="wikitable"
{| class="wikitable"
! Step !! cmd_type !! host to detector !! detector to host
!Step!!cmd_type!!host to detector!!detector to host
|-
|-
| Configure || 0x13 || [uploadId:4 LE] || [status:1][totalSize:4 LE]
|Configure||0x13||[uploadId:4 LE]||[status:1][totalSize:4 LE]
|-
|-
| Buffer || 0x14 || [bufId:4 LE][numBytes:4 LE] || [bufId:4 LE][numBytes:4 LE][data]
|Buffer||0x14||[bufId:4 LE][numBytes:4 LE]||[bufId:4 LE][numBytes:4 LE][data]
|}
|}


Line 671: Line 671:
image transfers as 65536 chunks of 1024 bytes.
image transfers as 65536 chunks of 1024 bytes.


=== Recovered files ===
===Recovered files===


A sweep of the unit returned 18 readable blobs:
A sweep of the unit returned 18 readable blobs:


{| class="wikitable"
{| class="wikitable"
! Upload ID !! Size (bytes) !! Contents
!Upload ID!!Size (bytes)!!Contents
|-
|-
| 0xFD || 67108864 || Full 64 MB NOR flash image
|0xFD||67108864||Full 64 MB NOR flash image
|-
|-
| 0xFF || 16777216 || 16 MB region (firmware / FPGA mirror or image buffer)
|0xFF||16777216||16 MB region (firmware / FPGA mirror or image buffer)
|-
|-
| 0xFE || 524288 || Bootloader (512 KB; SPI loader, Nios reset code)
|0xFE||524288||Bootloader (512 KB; SPI loader, Nios reset code)
|-
|-
| 0x10 || 6815783 || Calibration map, dose level 1
|0x10||6815783||Calibration map, dose level 1
|-
|-
| 0x11 || 6815783 || Calibration map, dose level 2
|0x11||6815783||Calibration map, dose level 2
|-
|-
| 0x12 || 6815783 || Calibration map, dose level 3
|0x12||6815783||Calibration map, dose level 3
|-
|-
| 0x06 || 49254 || Table referencing conditioner/generator serial UA2010-8U005
|0x06||49254||Table referencing conditioner/generator serial UA2010-8U005
|-
|-
| 0x50 || 19938 || Per mode calibration coefficients
|0x50||19938||Per mode calibration coefficients
|-
|-
| 0x51 || 19582 || Per mode calibration coefficients
|0x51||19582||Per mode calibration coefficients
|-
|-
| 0x07 || 12187 || Sensor conversion table (text; see Sensor Readout)
|0x07||12187||Sensor conversion table (text; see Sensor Readout)
|-
|-
| 0x72 || 3001 || Shock / drop event log (text)
|0x72||3001||Shock / drop event log (text)
|-
|-
| 0x0E || 624 || Panel geometry / configuration (binary)
|0x0E||624||Panel geometry / configuration (binary)
|-
|-
| 0x71 || 504 || Host list / registration record (see Host Registration)
|0x71||504||Host list / registration record (see Host Registration)
|-
|-
| 0x0F || 233 || Host to detector compatibility table (text)
|0x0F||233||Host to detector compatibility table (text)
|-
|-
| 0x08 || 62 || Serial and model strings
|0x08||62||Serial and model strings
|-
|-
| 0x0A || 48 || Manufacturing codes
|0x0A||48||Manufacturing codes
|-
|-
| 0x52 || 30 || Serial string
|0x52||30||Serial string
|-
|-
| 0x0B || 24 || Small marker / identifier
|0x0B||24||Small marker / identifier
|}
|}


=== Flash image layout (upload ID 0xFD) ===
===Flash image layout (upload ID 0xFD)===


A block scan of the 64 MB image shows the following regions:
A block scan of the 64 MB image shows the following regions:


{| class="wikitable"
{| class="wikitable"
! Range !! Contents
!Range!!Contents
|-
|-
| 0x000000 to 0x800000 || Firmware and FPGA configuration
|0x000000 to 0x800000||Firmware and FPGA configuration
|-
|-
| 0x800000 to 0x940000 || Sparse configuration area
|0x800000 to 0x940000||Sparse configuration area
|-
|-
| 0x940000 || Host list / registration record (matches upload ID 0x71)
|0x940000||Host list / registration record (matches upload ID 0x71)
|-
|-
| 0x1000000 to 0x2800000 || Calibration and image data (16 to 40 MB)
|0x1000000 to 0x2800000||Calibration and image data (16 to 40 MB)
|-
|-
| 0x2800000 to 0x4000000 || Erased / unused (40 to 64 MB)
|0x2800000 to 0x4000000||Erased / unused (40 to 64 MB)
|}
|}


Line 737: Line 737:
0x940000, confirming that the 504 byte 0x71 read maps to this flash region.
0x940000, confirming that the 504 byte 0x71 read maps to this flash region.


=== Notes on individual files ===
===Notes on individual files===


* '''0x07 (sensor table)''': plain text, header DetectorSerialNumber = UA45829-7, revision 1.2. Lists every sensor by name, command (0x7902), and sensorId. Also carries panel geometry in its [Common] section: 16 bit depth, 2048 by 2048 pixels, active area from (12, 12) to (2035, 2035), pixel pitch 0.2 mm, corner radius 1416.8, panel saturation 150.
*'''0x07 (sensor table)''': plain text, header DetectorSerialNumber = UA45829-7, revision 1.2. Lists every sensor by name, command (0x7902), and sensorId. Also carries panel geometry in its [Common] section: 16 bit depth, 2048 by 2048 pixels, active area from (12, 12) to (2035, 2035), pixel pitch 0.2 mm, corner radius 1416.8, panel saturation 150.
* '''0x10, 0x11, 0x12 (calibration maps)''': three distinct blobs of identical size, corresponding to the low, medium, and high dose calibration sets. Each begins with the firmware version and serial (header bytes 01 06 00 04 02 00 01 03 followed by the serial). Required to apply gain and offset correction to raw images.
*'''0x10, 0x11, 0x12 (calibration maps)''': three distinct blobs of identical size, corresponding to the low, medium, and high dose calibration sets. Each begins with the firmware version and serial (header bytes 01 06 00 04 02 00 01 03 followed by the serial). Required to apply gain and offset correction to raw images.
* '''0xFE (bootloader)''': contains the strings spi_load.S and ../../boot and Nios II reset vector code.
*'''0xFE (bootloader)''': contains the strings spi_load.S and ../../boot and Nios II reset vector code.
* '''0x72 (shock log)''': text records of drop / vibration events with timestamps and per axis values; the same data is mirrored in the detector's small onboard EEPROM.
*'''0x72 (shock log)''': text records of drop / vibration events with timestamps and per axis values; the same data is mirrored in the detector's small onboard EEPROM.
* '''0x06''': references a different serial, UA2010-8U005, likely the conditioner or generator board rather than the panel.
*'''0x06''': references a different serial, UA2010-8U005, likely the conditioner or generator board rather than the panel.


=== Significance ===
===Significance===


The complete flash image and all calibration data are recoverable over the
The complete flash image and all calibration data are recoverable over the
Line 754: Line 754:




 
===Known Dead Ends===
=== Known Dead Ends ===


Things that were tried and did not work or led nowhere:
Things that were tried and did not work or led nowhere:


; 0xBEEF (48879) as reply port
;0xBEEF (48879) as reply port
: This was a bug in early test scripts. The port has no meaning in the protocol. Use 5550.
:This was a bug in early test scripts. The port has no meaning in the protocol. Use 5550.


; CmdFlag=1 as data packet flag
;CmdFlag=1 as data packet flag
: Early scripts had the URP fields swapped, setting CmdFlag=1 on data packets. The detector ignores all PDAP content in these packets. Power cycle the detector if this happened, it may retain stale port state.
:Early scripts had the URP fields swapped, setting CmdFlag=1 on data packets. The detector ignores all PDAP content in these packets. Power cycle the detector if this happened, it may retain stale port state.


; Image data on alternate ports
;Image data on alternate ports
: Tried listening on 48879, 6660, 5550, 8100, 1050, 6661, 9999, 4444, 7000, 7001, 9001. Nothing arrived on any of them.
:Tried listening on 48879, 6660, 5550, 8100, 1050, 6661, 9999, 4444, 7000, 7001, 9001. Nothing arrived on any of them.


; PORT_SETUP byte order (big-endian)
;PORT_SETUP byte order (big-endian)
: Current implementation sends port fields as big-endian. If the detector reads them as little-endian it computes port 44565 and 1050 instead of 5550 and 6660, which would explain why no image data arrives. Not yet confirmed.
:Current implementation sends port fields as big-endian. If the detector reads them as little-endian it computes port 44565 and 1050 instead of 5550 and 6660, which would explain why no image data arrives. Not yet confirmed.


; Image data streaming automatically after EXECUTE_SCRIPT
;Image data streaming automatically after EXECUTE_SCRIPT
: Frames may not push during execution at all. The detector may require an explicit IMAGE_RETRIVAL_REQUEST (cmd_type=0x41) and IMAGE_RETRIVAL (cmd_type=0x98) after the 0x30000 notification before it streams anything. Not yet tested.
:Frames may not push during execution at all. The detector may require an explicit IMAGE_RETRIVAL_REQUEST (cmd_type=0x41) and IMAGE_RETRIVAL (cmd_type=0x98) after the 0x30000 notification before it streams anything. Not yet tested.




== Teardown / Internal Pictures / Hardware analysis ==
==Teardown / Internal Pictures / Hardware analysis==
<div style="float:left; display:flex; gap:8px;">
<div style="float:left; display:flex; gap:8px;">
[[File:GE Flashpad under the hood.jpg|thumb|none|220px|the Carbon fiber sleeve is held by 9 screws and can taken off without force.]]
[[File:GE Flashpad under the hood.jpg|thumb|none|220px|the Carbon fiber sleeve is held by 9 screws and can taken off without force.]]