736 lines
42 KiB
C
736 lines
42 KiB
C
/*
|
|
* H8/536 focused SCI RX/TX pseudocode from build\rom_decompiled.json
|
|
*
|
|
* This is a protocol-oriented reconstruction from decompiler JSON metadata.
|
|
* It is intentionally phrased as candidate behavior: it summarizes evidence
|
|
* from the ROM without claiming source-level intent or a proven packet format.
|
|
*/
|
|
|
|
/* Candidate summary:
|
|
* - SCI1 TX 6-byte frame at H'F858-H'F85D: confidence high (0.95)
|
|
* reason: all required independent evidence groups were observed
|
|
* - SCI1 RX 6-byte frame captured at H'F868-H'F86D: confidence high (0.9)
|
|
* reason: RX count, copy, and checksum-validation evidence were observed; no explicit header/sync byte was identified
|
|
* caveat: candidate frame means six consecutive bytes within the observed RX timing/state machine, not a proven delimited packet
|
|
*/
|
|
|
|
/* Board path:
|
|
* Board trace ties the H8/536 SCI1 pins to a MAX202 RS232 transceiver.
|
|
* - TXD: H8 pin 66 P95/TXD <-> MAX202 pin 11
|
|
* evidence: MAX202 pin 11 traces to H8 pin 66
|
|
* - RXD: H8 pin 67 P96/RXD <-> MAX202 pin 12
|
|
* evidence: MAX202 pin 12 traces to H8 pin 67
|
|
*/
|
|
|
|
/* Manual anchors used by the decompiler metadata:
|
|
* - Manual/0900766b802125d0.md:15748 SCI register map for RDR/TDR/SCR/SSR
|
|
* - Manual/0900766b802125d0.md:15794 RDR stores received data and is CPU-readable
|
|
* - Manual/0900766b802125d0.md:15823 TDR holds the next byte to transmit
|
|
* - Manual/0900766b802125d0.md:15976 SCR.TIE enables/disables TXI on TDRE
|
|
* - Manual/0900766b802125d0.md:15993 SCR.RIE enables RXI and ERI
|
|
* - Manual/0900766b802125d0.md:16008 SCR.TE enables the transmitter
|
|
* - Manual/0900766b802125d0.md:16028 SCR.RE enables the receiver
|
|
* - Manual/0900766b802125d0.md:16090 SSR flags are cleared by writing zero
|
|
* - Manual/0900766b802125d0.md:16100 SSR.TDRE means TDR can accept the next byte
|
|
* - Manual/0900766b802125d0.md:16116 SSR.RDRF means received data reached RDR
|
|
* - Manual/0900766b802125d0.md:16127 SSR.ORER reports receive overrun
|
|
* - Manual/0900766b802125d0.md:16140 SSR.FER reports framing errors
|
|
* - Manual/0900766b802125d0.md:16147 SSR.PER reports parity errors
|
|
* - Manual/0900766b802125d0.md:2417 FP-80 H8/536 pin 66 is P95/TXD
|
|
* - Manual/0900766b802125d0.md:2418 FP-80 H8/536 pin 67 is P96/RXD
|
|
* - Manual/0900766b802125d0.md:11192 Port 9 carries SCI1 and SCI2 serial signals
|
|
* - Manual/0900766b802125d0.md:11201 P96 is RXD1 input
|
|
* - Manual/0900766b802125d0.md:11202 P95 is TXD1 output
|
|
* - Manual/0900766b802125d0.md:15725 SCI1 RXD input pin
|
|
* - Manual/0900766b802125d0.md:15726 SCI1 TXD output pin
|
|
* - Manual/0900766b802125d0.md:15750 SCI register table starts with SCI1 RDR/TDR/SMR/SCR/SSR/BRR
|
|
* - Manual/0900766b802125d0.md:15758 SCI register table lists SCI2 RDR/TDR/SMR/SCR/SSR/BRR
|
|
* - Manual/0900766b802125d0.md:15794 RDR receive data register
|
|
* - Manual/0900766b802125d0.md:15823 TDR transmit data register
|
|
* - Manual/0900766b802125d0.md:15969 SCR enables and disables SCI functions
|
|
* - Manual/0900766b802125d0.md:16009 SCR.TE makes the TXD pin output
|
|
* - Manual/0900766b802125d0.md:16029 SCR.RE makes the RXD pin input
|
|
* - Manual/0900766b802125d0.md:16090 SSR contains transmit/receive status flags
|
|
* - Manual/0900766b802125d0.md:10560 SYSCR2 controls port 9 pin functions
|
|
* - Manual/0900766b802125d0.md:10631 SYSCR2.P9SCI2E controls the SCI2 functions of P92-P94
|
|
*/
|
|
|
|
/* SCI1 link layer:
|
|
* - 8E1 SCI characters carry the 6 protocol bytes; async 8-bit even parity 1 stop, clock internal, SMR=H'24, BRR=H'07, SCR=H'3C
|
|
* - baud is clock-dependent; pass --clock-hz on the decompiler for bps.
|
|
* - No SCI1 RXI/TXI DTC vector entries are present in JSON; RX/TX are modeled as CPU ISR paths.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
typedef uint8_t u8;
|
|
typedef uint16_t u16;
|
|
|
|
#define BIT(n) (1u << (n))
|
|
extern volatile u8 MEM8[0x10000];
|
|
|
|
#define SCI1_SCR MEM8[0xFEDAu]
|
|
#define SCI1_TDR MEM8[0xFEDBu]
|
|
#define SCI1_SSR MEM8[0xFEDCu]
|
|
#define SCI1_RDR MEM8[0xFEDDu]
|
|
|
|
#define SCI_SCR_TIE 0x80u
|
|
#define SCI_SCR_RIE 0x40u
|
|
#define SCI_SCR_TE 0x20u
|
|
#define SCI_SCR_RE 0x10u
|
|
#define SCI_SSR_TDRE 0x80u
|
|
#define SCI_SSR_RDRF 0x40u
|
|
#define SCI_SSR_ORER 0x20u
|
|
#define SCI_SSR_FER 0x10u
|
|
#define SCI_SSR_PER 0x08u
|
|
|
|
#define SCI1_TX_FRAME_LENGTH 6u
|
|
#define SCI1_TX_FRAME_BASE 0xF858u
|
|
#define SCI1_TX_FRAME_BYTE(n) MEM8[(u16)(SCI1_TX_FRAME_BASE + (n))]
|
|
#define SCI1_TX_FRAME_CHECKSUM SCI1_TX_FRAME_BYTE(5u)
|
|
#define SCI1_TX_INDEX MEM8[0xF9C2u]
|
|
#define TX_FRAME_LENGTH SCI1_TX_FRAME_LENGTH
|
|
#define TX_FRAME(n) MEM8[(u16)(0xF858u + (n))]
|
|
#define TX_INDEX SCI1_TX_INDEX
|
|
|
|
#define RX_FRAME_LENGTH 6u
|
|
#define RX_CAPTURE(n) MEM8[(u16)(0xF868u + (n))]
|
|
#define RX_FRAME(n) MEM8[(u16)(0xF860u + (n))]
|
|
#define RX_INDEX MEM8[0xF9C3u]
|
|
#define RX_INTERBYTE_TIMEOUT MEM8[0xF9C1u]
|
|
#define RX_COMPLETE_TIMER MEM8[0xF9C5u]
|
|
#define RX_ERROR_LATCH MEM8[0xFAA4u]
|
|
#define RX_ERROR_LATCH_PHYSICAL_ERROR 0x80u
|
|
|
|
/* Candidate Protocol Semantics
|
|
* confidence: medium-high (0.9)
|
|
* caveat: Semantic names are candidates only. The analyzer reports byte roles, command values, dispatch targets, and response staging patterns observed in code; it does not prove source-level intent or protocol documentation.
|
|
* byte layout:
|
|
* - byte0: op_flags (medium-high) - low three bits select a command; upper bits are preserved or gated in some paths
|
|
* - byte1: addr_page_flags (medium) - candidate high/page byte for logical point/index; bit 7 is tested as a control flag
|
|
* - byte2: addr_offset (medium) - candidate low/offset byte for logical point/index
|
|
* - byte3: value_hi (medium) - candidate high byte of a word value
|
|
* - byte4: value_lo (medium) - candidate low byte of a word value
|
|
* - byte5: checksum (high) - 0x5A-seeded XOR of bytes 0..4
|
|
* dispatch: command_low3 = RX_FRAME(0) & 0x07; observed H'00, H'01, H'02, H'04, H'05, H'06, H'07
|
|
* dispatcher split: FAA2 == 0 accepts initial/idle commands H'00, H'01, H'02, H'07; FAA2 != 0 accepts continuation commands H'04, H'05, H'06, H'07
|
|
* dispatcher caveat: Initial dispatch follows checksum validation and RX error handling. Command 1 is only on the initial/idle path and is also gated by F861.bit7 == 0.
|
|
* dispatch evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BC24, H'BC26, H'BC29, H'BC2B, H'BC2E, H'BC30, H'BC45, H'BC47, H'BC4A, H'BC4C, H'BC4F, H'BC51, H'BC54, H'BC56
|
|
* index decoder: RX[1:2] -> logical index via loc_622B (medium)
|
|
* command candidates:
|
|
* - H'00 set_value_acked: candidate write of RX[3:4] into primary/current tables, followed by a response; handler H'BC69; responses response_at_BCCD
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0
|
|
* - H'01 read_value: initial/idle-path primary table read only, followed by an odd response staging sequence; handler H'BCD7; responses response_at_BCFA
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0 && F861.bit7 == 0
|
|
* note: Only accepted on the initial/idle dispatcher path: valid checksum/no RX error, FAA2 == 0, and F861.bit7 == 0.
|
|
* note: BCD7 stages F850=0x04, writes F851 from F861 and then overwrites F851 from F862.
|
|
* note: BCD7 reads the primary table word at E000 + 2*selector; F854 receives the low byte and F853 receives the high byte.
|
|
* note: F852 is not freshly written in the BCD7 handler, so do not describe the response as a fixed 04 00 QQ hi lo frame.
|
|
* - H'02 clear_or_abort: candidate clear/abort path with no immediate response builder; handler H'BD04; responses none
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0
|
|
* - H'04 set_value_no_immediate_reply: candidate write/update path that stores a value without an immediate serial response; handler H'BD0E; responses none
|
|
* availability: valid checksum/no RX physical error && FAA2 != 0
|
|
* - H'05 ack_or_clear_pending: continuation-only conditional acknowledgement/session clear path; handler H'BD80; responses none
|
|
* availability: valid checksum/no RX physical error && FAA2 != 0
|
|
* note: Only accepted on the continuation dispatcher path when FAA2 != 0.
|
|
* note: For selector 0x0040, frame 05 00 40 00 00 1F performs no response staging.
|
|
* note: The handler clears FAA3/FAA2; F9B5 advances only when FAA2.bit3 was set from a queued report.
|
|
* note: If FAA2 == 0, command 5 falls through the initial dispatcher instead of doing acknowledgement work.
|
|
* - H'06 set_secondary_value: candidate secondary-table value write path; handler H'BDDB; responses none
|
|
* availability: valid checksum/no RX physical error && FAA2 != 0
|
|
* - H'07 retransmit_or_error_reply: candidate retransmit path; retry/error handling also builds a command 0x07 RX-payload echo; handler H'BE05; responses response_at_BE22
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0 OR valid checksum/no RX physical error && FAA2 != 0
|
|
* note: loc_BE4D is a retry/error echo path: F850=0x07 and F861-F864 are copied into F851-F854 before loc_BA26.
|
|
* note: Observed frame 07 80 40 20 90 2D means RX bytes F861-F864 were 80 40 20 90; it is not a table value.
|
|
* command effects:
|
|
* - H'00 set_value_acked: Candidate acknowledged set: writes value bytes to primary/current tables, flags the index, and stages an echo-style response.
|
|
* effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
|
* effect: table_write_candidate; target current_value_table_candidate; source same candidate value written to the primary table; table H'E800
|
|
* effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
|
* evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCB5, H'BCBD, H'BCC5, H'BCCD
|
|
* - H'01 read_value: Initial/idle candidate read: reads the primary table and stages an odd value response with F852 possibly stale.
|
|
* effect: table_read_candidate; target primary_value_table_candidate; table H'E000
|
|
* effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
|
* evidence: H'BC08, H'BC0C, H'BC24, H'BC26, H'BCD7, H'BCE0, H'BCE8, H'BCF0, H'BCF6, H'BCDC, H'BCE4, H'BCFA
|
|
* - H'02 clear_or_abort: Candidate clear/abort: clears serial session state without an observed immediate response.
|
|
* effect: state_clear_candidate; target serial_session_flags_candidate; clear bit 7; state H'FAA2
|
|
* evidence: H'BC08, H'BC0C, H'BC29, H'BC2B
|
|
* - H'04 set_value_no_immediate_reply: Candidate deferred set: writes value bytes and flags the index without an observed immediate response.
|
|
* effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
|
* effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
|
* evidence: H'BC08, H'BC0C, H'BC45, H'BC47
|
|
* - H'05 ack_or_clear_pending: Continuation-only ACK/session clear: clears FAA3/FAA2 and only advances F9B5 when queued-report FAA2.bit3 was set; selector 0x0040 has no response.
|
|
* effect: conditional_ack_session_clear_candidate; target selected event/pending state; when FAA2 != 0, clear FAA3/FAA2; advance F9B5 only if FAA2.bit3 was set from queued-report state; selector 0x0040 stages no response; selector H'0040 has no response
|
|
* evidence: H'BC08, H'BC0C, H'BC4A, H'BC4C
|
|
* - H'06 set_secondary_value: Candidate secondary set: writes value bytes to the secondary table and flags the index.
|
|
* effect: table_write_candidate; target secondary_value_table_candidate; source RX[3:4] value bytes; table H'E400
|
|
* effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 6; table H'EC00
|
|
* evidence: H'BC08, H'BC0C, H'BC4F, H'BC51
|
|
* - H'07 retransmit_or_error_reply: Candidate retransmit/error reply: reuses prior TX bytes or copies RX payload bytes behind an explicit 0x07 retry/error echo.
|
|
* effect: retransmit_candidate; target TX staging bytes H'F850-H'F854 before loc_BA26; source previous TX frame bytes H'F858-H'F85C
|
|
* effect: retry_error_echo_candidate; target F850=0x07, F851-F854=F861-F864 before loc_BA26; source RX payload bytes F861-F864; 07 80 40 20 90 2D echoes RX payload 80 40 20 90; it is not a table value
|
|
* effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
|
* evidence: H'BC08, H'BC0C, H'BC2E, H'BC30, H'BC54, H'BC56, H'BE09, H'BE11, H'BE19, H'BE22
|
|
* response schemas:
|
|
* - response_at_BB43: byte0=computed; byte1=computed; byte2=computed; byte3=current_value_table_candidate; byte4=current_value_table_candidate
|
|
* evidence: H'BB1C, H'BB2B, H'BB20, H'BB3F, H'BB39
|
|
* - response_at_BCCD: byte0=0x04; byte1=rx[1]; byte2=rx[2]; byte3=rx[3]; byte4=rx[4]
|
|
* evidence: H'BCB0, H'BCB9, H'BCC1, H'BCC9
|
|
* - response_at_BCFA: byte0=0x04; byte1=rx[2]; byte2=stale/unchanged; byte3=primary_value_table_candidate; byte4=primary_value_table_candidate
|
|
* note: Command 1 BCD7 staging is odd: F850=0x04; F851 is written from F861 then overwritten by F862.
|
|
* note: The primary table word is read from E000 + 2*selector; F854/F853 receive low/high value bytes.
|
|
* note: F852 may be stale or unchanged in this handler; avoid a fixed 04 00 QQ hi lo response shape.
|
|
* evidence: H'BCD7, H'BCE8, H'BCF6, H'BCF0
|
|
* - response_at_BE22: byte0=tx[0]; byte1=tx[1]; byte2=tx[2]; byte3=tx[3]; byte4=tx[4]
|
|
* evidence: H'BE09, H'BE11, H'BE19
|
|
* - ... 1 more candidate response schemas
|
|
* table map candidates:
|
|
* - primary_value_table_candidate at H'E000 (word_value); observed read, write
|
|
* evidence: H'19E3, H'1A03, H'1A3D, H'1A6B, H'3F8C, H'4077, H'BC75, H'BC95, H'BCEC, H'BD1A, H'BD35
|
|
* - secondary_value_table_candidate at H'E400 (word_value); observed read, write
|
|
* evidence: H'19AA, H'1A4B, H'1A5B, H'1A81, H'1AB4, H'1AC1, H'407B, H'BDE5
|
|
* - current_value_table_candidate at H'E800 (word_value); observed read, write
|
|
* evidence: H'1A09, H'1A71, H'3F90, H'407F, H'BB35, H'BC79, H'BC99, H'BD1E
|
|
* - flag_table_candidate at H'EC00 (bit_flags); observed write
|
|
* evidence: H'4088, H'BC82, H'BC9D, H'BD22, H'BD39, H'BDE9
|
|
* panel selector semantics:
|
|
* - 0x0013 slave_and_iris_mblack_link_lamps: Selector 0x0013 is a two-bit lamp/status word. ROM dispatch H'2E06 reads current table word H'E826 and fans bit 15 and bit 14 into panel latch RAM.
|
|
* current word: H'E826; dispatch: H'2E06
|
|
* 0x8000 -> SLAVE lamp: sets F791.6 and F713.4; RAM F791.6, F713.4
|
|
* 0x4000 -> IRIS/M.BLACK LINK lamp: sets F791.5 and F716.7; RAM F791.5, F716.7
|
|
* observed values: 0x8000 SLAVE lamp on; 0x4000 IRIS/M.BLACK LINK lamp on; 0x0000 SLAVE and IRIS/M.BLACK LINK latch bits clear through H'2E06
|
|
* state machine: iris_mblack_link_closed_loop_state_candidate: Bench-proven closed loop: the RCP reports local IRIS/M.BLACK LINK intent, the CCU ACKs selector 0x0013, then the CCU mirrors the accepted selector state back with command 0. The mirrored state controls the next toggle direction.
|
|
* frames: active report 00 00 13 40 00 09; clear report 00 00 13 00 00 49; ACK 05 00 13 00 00 4C; mirror active 00 00 13 40 00 09; mirror clear 00 00 13 00 00 49
|
|
* local trigger candidates: provisional_iris_mblack_link_button_toggle_report F006.7 / F6DB.7: When F6DB.7 is asserted and F731 <= 3, the ROM toggles current-table bit 14 at H'E826 based on F791.5, then queues selector 0x0013 through loc_3E54.; H'1FE8/H'1FFB: Adjacent local helpers set or clear current-table bit 15 at H'E826 and queue selector 0x0013.
|
|
* evidence: bench: 00 00 13 80 00 C9 lights far-right SLAVE lamp, bench: 00 00 13 40 00 09 lights IRIS/M.BLACK LINK lamp, ROM: H'2E06-H'2E32 tests H'E826 bits 15/14 and sets/clears F791/F713/F716 latch bits
|
|
* - 0x0024 lcd_selector_button_lamp: Bench-visible LCD selector-button lamp lane.
|
|
* current word: H'E848; dispatch: dispatch unknown
|
|
* observed values: 0x8000 LCD selector-button lamp visible; 0x0000 lamp remained visible at 0.5 s in isolation run
|
|
* - 0x0082 iris_readout_lane: Bench-visible IRIS seven-segment/display lane.
|
|
* current word: H'E904; dispatch: dispatch unknown
|
|
* observed values: 0x8000 IRIS display OP; 0x4000 IRIS display 1.4; 0x0000 IRIS display blank
|
|
* - 0x0083 combined_iris_shutter_master_gain_status_lane: Bench-visible combined status/readout lane; clear behavior appears latched or copied elsewhere.
|
|
* current word: H'E906; dispatch: dispatch unknown
|
|
* observed values: 0x8000 IRIS AUTO, SHUTTER OFF, MASTER GAIN -3; 0x0000 same visible state remained at 0.5 s
|
|
* - 0x0093 white_balance_black_flare_mode_lane: Bench-visible white-balance and black/flare lamp lane.
|
|
* current word: H'E926; dispatch: dispatch unknown
|
|
* observed values: 0x8000 BLACK/FLARE MANUAL plus white-balance PRESET; 0x4000 BLACK/FLARE MANUAL plus white-balance AUTO; 0x2000 BLACK/FLARE MANUAL plus white-balance MANUAL; 0x0000 BLACK/FLARE MANUAL plus white-balance MANUAL
|
|
* state variable candidates:
|
|
* - event_queue_read_cursor_candidate H'F9B4: reads 1, writes 2; bits 5
|
|
* evidence: H'BE78, H'BE95, H'BE99
|
|
* - event_queue_write_or_pending_cursor_candidate H'F9B5: reads 2, writes 6; bits 7
|
|
* evidence: H'405F, H'BAF2, H'BD6D, H'BD71, H'BDC8, H'BDCC, H'BDF3, H'BDF7
|
|
* - event_queue_base_or_current_slot_candidate H'F9B9: reads 1, writes 0
|
|
* evidence: H'BE70
|
|
* - serial_tx_busy_timer_candidate H'F9C0: reads 2, writes 8
|
|
* evidence: H'BA26, H'BA2C, H'BAA2, H'BADA, H'BAE1, H'BAE8, H'BE1D, H'BE3E, H'BEEE, H'BEF4
|
|
* - idle_heartbeat_gate_countdown_candidate H'F9C4: reads 2, writes 3
|
|
* evidence: H'4046, H'40E0, H'BA31, H'BF27, H'BF2D
|
|
* - rx_session_timeout_candidate H'F9C5: reads 1, writes 3
|
|
* evidence: H'BB9E, H'BEE4, H'BF31, H'BF37
|
|
* - ... 7 more state-variable candidates
|
|
* retry/error model candidate:
|
|
* - checksum path: 0x5A-seeded XOR over RX[0..4] differs from RX[5] -> loc_BE29
|
|
* - retry path: counter H'FAA6, threshold 2; Candidate retry path clears/consults serial flags, increments FAA6, compares it with 2, and when still below the apparent limit enters loc_BE4D to stage a command 0x07 retry/error echo of RX payload bytes F861-F864.
|
|
* echo path: loc_BE4D: F850=0x07; F851-F854=F861-F864
|
|
* echo caveat: 07 80 40 20 90 2D echoes RX payload 80 40 20 90 and is not a table value.
|
|
* - command 0x07 path: Candidate retransmit/explicit command 0x07 path either copies previous TX frame bytes back to F850-F854 or stages an observed 0x07 response before loc_BA26.
|
|
* - evidence: H'BBD8, H'BBDC, H'BBE0, H'BBE4, H'BBE8, H'BBEC, H'BBF0, H'BE4D, H'BE56, H'BE5E, H'BE66, H'BE52, H'BE5A, H'BE62, H'BE6A, H'BE29, H'BE2D, H'BE33, H'BE37, H'BE43, H'BE47, H'BE05, H'BE0D, H'BE15, H'BE09, H'BE11, H'BE19, H'BE22
|
|
* gate/queue state machine candidate:
|
|
* - main_loop_may_enter_report_builder: FAA2 == 0 && F9C0 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)); Main-loop report gate; session must be idle, TX busy timer clear, and RX gate open.
|
|
* - idle_heartbeat_report_may_enqueue: F9C4 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)) && F9B0 == F9B5; Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'0000 for the later loc_BAF2 -> loc_BA26 send path.
|
|
* enqueues report H'0000
|
|
* write semantics: loc_4067 is MOV:G.W #H'00, @(-H'0790,R2): the byte immediate is zero-extended by the word destination, so the queue slot becomes H'0000.
|
|
* runtime-confirmed frame 00 00 00 00 80 DA via loc_4046 -> loc_BAF2 -> loc_BB08 -> loc_BB1C -> loc_BB20 -> loc_BB2B -> loc_BA26
|
|
* - queue_has_pending_report: F9B5 != F9B0; Queue/pending cursor gate; non-empty state stages through BB43 before loc_BA26.
|
|
* - periodic_resend_may_fire: (FAA5 & FAA3 & 0x80) != 0 && F9C6 == 0 && F9C8 != 0 after countdown; Resend gate masks pending state with FAA5, checks F9C6/F9C8, then calls BA26 at BED5.
|
|
* - rx_completion_sets_session_timer: RX completion sets F9C5 (observed reload H'14) after the sixth byte is captured.
|
|
* - session_timeout_clears_gate_and_queue: When F9C5 is clear, loc_3FEF clears F9B5/F9B0 and clears FAA5.bit7; when nonzero, it sets FAA5.bit7.
|
|
* - idle_heartbeat_gate_initial_delay_loaded: Startup/init loads F9C4 with H'14 before the first idle/default report can be queued.
|
|
* - idle_heartbeat_gate_post_send_delay_loaded: loc_BA26 reloads F9C4 with H'07 after each send, matching the observed heartbeat spacing.
|
|
* - host_ack_can_advance_queue: Command 0x05 is a continuation-only ACK/session clear path: it clears FAA3/FAA2 and advances F9B5 only when queued-report FAA2.bit3 was set. Selector 0x0040 has no response; if FAA2 == 0 the command falls through instead of doing ACK work.; commands H'05
|
|
* - caveat: Many panel controls may require host/session traffic before reporting. Observed autonomous call/camera-power indexes are runtime/capture overlays, not ROM constants.
|
|
* - evidence: H'3FD3, H'3FD7, H'3FD9, H'3FDD, H'3FDF, H'3FE3, H'3FE5, H'3FE9, H'3FEB, H'3FEF, H'3FF3, H'3FF5, H'3FF9, H'3FFD, H'4001, H'4003, H'4005, H'4007, H'4046, H'404A, H'404C, H'4050, H'4052, H'4056, H'4058, H'4059, H'405D, H'405F, H'4063, H'4065, H'4067, H'406C, H'4070, H'BAF2, H'BAF6, H'BAF8, H'BAFC, H'BAFE, H'BB00, H'BB04, H'BB06, H'BB08, H'BB0C, H'BB0E, H'BB11, H'BB13, H'BB15, H'BB17, H'BB19, H'BB1C, H'BB20, H'BB24, H'BB26, H'BB29, H'BB2B, H'BB2F, H'BB33, H'BB35, H'BB39, H'BB3D, H'BB3F, H'BB43, H'BE9E, H'BEA2, H'BEA5, H'BEA9, H'BEAD, H'BEAF, H'BEB3, H'BEB5, H'BEB9, H'BEBB, H'BEBF, H'BEC1, H'BEC5, H'BECB, H'BECF, H'BED1, H'BED5
|
|
* TX/autonomous report model candidate:
|
|
* - loc_BB43 -> loc_BA26: bytes 0..2 encode candidate logical index/report id; bytes 3..4 come from current_value_table_candidate; byte5 is 0x5A XOR checksum
|
|
* - observed overlay candidates: heartbeat_or_idle_report_candidate: 00 00 00 00 80 DA; call_button_report_candidate: 00 00 15 80 00 CF, 00 00 15 00 00 4F; camera_power_report_candidate: 00 00 07 80 00 DD
|
|
* - runtime confirmation: idle_heartbeat_report_runtime_confirmation: report H'0000 emits 00 00 00 00 80 DA; MOV:G.W #H'00 writes H'0000 to the queue slot
|
|
* - consistency idle_heartbeat_report_id_width: pass; Decompiler mnemonic MOV:G.W and emulator execution now agree that the H'00 immediate at loc_4067 is zero-extended to report H'0000.
|
|
* - caveat: Real captures supplied so far show only heartbeat/idle, call, and camera-power autonomous TX frames. Other panel controls may require a host/device request or state transition before the firmware reports them.
|
|
* - evidence: H'BB1C, H'BB20, H'BB2B, H'BB39, H'BB3F, H'BB43
|
|
* heartbeat/periodic resend candidate:
|
|
* - F9C6 reload H'01F4: Candidate periodic report/heartbeat timer reload.
|
|
* - F9C8 reload H'14: Candidate periodic resend countdown/retry spacing value.
|
|
* - FAA3 mask H'80: Candidate bit/mask that marks an autonomous report pending.
|
|
* - BED5 resend path: Candidate periodic resend path feeding the TX staging/send-builder flow.
|
|
* - evidence: H'BB46, H'BEC5, H'BB4C, H'BB51, H'BECB, H'BED5
|
|
* interrupt/timer architecture candidate:
|
|
* - FRT1 OCIA H'BEEA: Candidate periodic tick ISR for serial busy, interbyte, and resend counters.
|
|
* - FRT2 OCIA H'BF23: Candidate periodic tick ISR for idle heartbeat/report and RX session counters.
|
|
* - H'F9C0 tx_report_gate_counter_candidate: candidate gate counter used before entering the report builder.
|
|
* - H'F9C1 rx_interbyte_timeout_candidate: candidate RX interbyte timeout counter.
|
|
* - H'F9C6 periodic_resend_cadence_counter_candidate: candidate periodic resend/heartbeat cadence counter.
|
|
* - H'F9C4 idle_heartbeat_gate_countdown_candidate: candidate idle/default report enqueue countdown.
|
|
* - H'F9C5 rx_session_timeout_candidate: candidate RX/session maintenance timeout counter.
|
|
* - evidence: H'BEEA, H'BEEE, H'BEF2, H'BEF4, H'BEF8, H'BEFC, H'BEFE, H'BF02, H'BF06, H'BF08, H'BF23, H'BF27, H'BF2B, H'BF2D, H'BF31, H'BF35, H'BF37
|
|
*/
|
|
|
|
static u8 sci1_rx_candidate_command(void)
|
|
{
|
|
return (u8)(RX_FRAME(0) & 0x07u);
|
|
}
|
|
|
|
static u16 sci1_rx_candidate_value(void)
|
|
{
|
|
return (u16)(((u16)RX_FRAME(3) << 8) | RX_FRAME(4));
|
|
}
|
|
|
|
static u16 sci1_rx_candidate_logical_index(void)
|
|
{
|
|
u8 page = RX_FRAME(1);
|
|
u8 offset = RX_FRAME(2);
|
|
|
|
if (page == 0u && offset <= 0x7Fu) {
|
|
return offset;
|
|
}
|
|
if (page == 1u) {
|
|
return (u16)(0x0080u + offset);
|
|
}
|
|
if (page == 2u && offset <= 0x7Fu) {
|
|
return (u16)(0x0180u + offset);
|
|
}
|
|
return 0x01FFu;
|
|
}
|
|
|
|
static bool sci1_candidate_main_report_gate_open(void)
|
|
{
|
|
bool session_idle = MEM8[0xFAA2u] == 0u;
|
|
bool rx_gate_open = (MEM8[0xFAA5u] & 0x80u) == 0u || MEM8[0xF9C3u] == 0u;
|
|
bool tx_timer_clear = MEM8[0xF9C0u] == 0u;
|
|
|
|
return session_idle && rx_gate_open && tx_timer_clear;
|
|
}
|
|
|
|
static bool sci1_candidate_report_queue_nonempty(void)
|
|
{
|
|
return MEM8[0xF9B5u] != MEM8[0xF9B0u];
|
|
}
|
|
|
|
static bool sci1_candidate_idle_heartbeat_enqueue_gate_open(void)
|
|
{
|
|
bool idle_timer_clear = MEM8[0xF9C4u] == 0u;
|
|
bool rx_gate_open = (MEM8[0xFAA5u] & 0x80u) == 0u || MEM8[0xF9C3u] == 0u;
|
|
bool queue_empty = MEM8[0xF9B0u] == MEM8[0xF9B5u];
|
|
|
|
return idle_timer_clear && rx_gate_open && queue_empty;
|
|
}
|
|
|
|
static void sci1_candidate_enqueue_idle_heartbeat_report(void)
|
|
{
|
|
if (!sci1_candidate_idle_heartbeat_enqueue_gate_open()) {
|
|
return;
|
|
}
|
|
|
|
/* loc_4067 writes MOV:G.W #H'00, so the queue report id is 0x0000. */
|
|
candidate_enqueue_report(0x0000u);
|
|
}
|
|
|
|
static bool sci1_candidate_periodic_resend_gate_open(void)
|
|
{
|
|
bool pending = (MEM8[0xFAA5u] & MEM8[0xFAA3u] & 0x80u) != 0u;
|
|
bool period_elapsed = MEM8[0xF9C6u] == 0u && MEM8[0xF9C7u] == 0u;
|
|
bool resend_countdown_active = MEM8[0xF9C8u] != 0u;
|
|
|
|
return pending && period_elapsed && resend_countdown_active;
|
|
}
|
|
|
|
void frt1_ocia_candidate_tick_isr(void)
|
|
{
|
|
/* Candidate periodic tick at H'BEEA: decrement nonzero serial counters. */
|
|
/* TX_REPORT_GATE_COUNTER_CANDIDATE: candidate gate counter used before entering the report builder. */
|
|
if (MEM8[0xF9C0u] != 0u) {
|
|
MEM8[0xF9C0u] = (u8)(MEM8[0xF9C0u] - 1u);
|
|
}
|
|
|
|
/* RX_INTERBYTE_TIMEOUT_CANDIDATE: candidate RX interbyte timeout counter. */
|
|
if (MEM8[0xF9C1u] != 0u) {
|
|
MEM8[0xF9C1u] = (u8)(MEM8[0xF9C1u] - 1u);
|
|
}
|
|
|
|
/* PERIODIC_RESEND_CADENCE_COUNTER_CANDIDATE: candidate periodic resend/heartbeat cadence counter. */
|
|
if (MEM8[0xF9C6u] != 0u) {
|
|
MEM8[0xF9C6u] = (u8)(MEM8[0xF9C6u] - 1u);
|
|
}
|
|
|
|
}
|
|
|
|
void frt2_ocia_candidate_tick_isr(void)
|
|
{
|
|
/* Candidate periodic tick at H'BF23: decrement nonzero serial counters. */
|
|
/* IDLE_HEARTBEAT_GATE_COUNTDOWN_CANDIDATE: candidate idle/default report enqueue countdown. */
|
|
if (MEM8[0xF9C4u] != 0u) {
|
|
MEM8[0xF9C4u] = (u8)(MEM8[0xF9C4u] - 1u);
|
|
}
|
|
|
|
/* RX_SESSION_TIMEOUT_CANDIDATE: candidate RX/session maintenance timeout counter. */
|
|
if (MEM8[0xF9C5u] != 0u) {
|
|
MEM8[0xF9C5u] = (u8)(MEM8[0xF9C5u] - 1u);
|
|
}
|
|
|
|
}
|
|
|
|
static void sci1_candidate_panel_selector_annotation(u16 logical_index, u16 value)
|
|
{
|
|
/* Known bench/ROM selector labels. This helper is commentary for the decompile. */
|
|
switch (logical_index) {
|
|
case 0x0013u:
|
|
/* 0x0013 slave_and_iris_mblack_link_lamps; current word H'E826; H'2E06. */
|
|
if ((value & 0x8000u) != 0u) {
|
|
/* SLAVE lamp: sets F791.6 and F713.4. */
|
|
} else {
|
|
/* SLAVE lamp: clears F791.6 and F713.4. */
|
|
}
|
|
if ((value & 0x4000u) != 0u) {
|
|
/* IRIS/M.BLACK LINK lamp: sets F791.5 and F716.7. */
|
|
} else {
|
|
/* IRIS/M.BLACK LINK lamp: clears F791.5 and F716.7. */
|
|
}
|
|
if (value == 0x8000u) {
|
|
/* SLAVE lamp on. */
|
|
}
|
|
if (value == 0x4000u) {
|
|
/* IRIS/M.BLACK LINK lamp on. */
|
|
}
|
|
if (value == 0x0000u) {
|
|
/* SLAVE and IRIS/M.BLACK LINK latch bits clear through H'2E06. */
|
|
}
|
|
break;
|
|
case 0x0024u:
|
|
/* 0x0024 lcd_selector_button_lamp; current word H'E848; dispatch unknown. */
|
|
if (value == 0x8000u) {
|
|
/* LCD selector-button lamp visible. */
|
|
}
|
|
if (value == 0x0000u) {
|
|
/* lamp remained visible at 0.5 s in isolation run. */
|
|
}
|
|
break;
|
|
case 0x0082u:
|
|
/* 0x0082 iris_readout_lane; current word H'E904; dispatch unknown. */
|
|
if (value == 0x8000u) {
|
|
/* IRIS display OP. */
|
|
}
|
|
if (value == 0x4000u) {
|
|
/* IRIS display 1.4. */
|
|
}
|
|
if (value == 0x0000u) {
|
|
/* IRIS display blank. */
|
|
}
|
|
break;
|
|
case 0x0083u:
|
|
/* 0x0083 combined_iris_shutter_master_gain_status_lane; current word H'E906; dispatch unknown. */
|
|
if (value == 0x8000u) {
|
|
/* IRIS AUTO, SHUTTER OFF, MASTER GAIN -3. */
|
|
}
|
|
if (value == 0x0000u) {
|
|
/* same visible state remained at 0.5 s. */
|
|
}
|
|
break;
|
|
case 0x0093u:
|
|
/* 0x0093 white_balance_black_flare_mode_lane; current word H'E926; dispatch unknown. */
|
|
if (value == 0x8000u) {
|
|
/* BLACK/FLARE MANUAL plus white-balance PRESET. */
|
|
}
|
|
if (value == 0x4000u) {
|
|
/* BLACK/FLARE MANUAL plus white-balance AUTO. */
|
|
}
|
|
if (value == 0x2000u) {
|
|
/* BLACK/FLARE MANUAL plus white-balance MANUAL. */
|
|
}
|
|
if (value == 0x0000u) {
|
|
/* BLACK/FLARE MANUAL plus white-balance MANUAL. */
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void provisional_iris_mblack_link_button_toggle_report(void)
|
|
{
|
|
/* Provisional name for ROM H'200E: When F6DB.7 is asserted and F731 <= 3, the ROM toggles current-table bit 14 at H'E826 based on F791.5, then queues selector 0x0013 through loc_3E54. */
|
|
/* Source F006.7 / F6DB.7; gate F731 <= 3; current state F791.5. */
|
|
if ((MEM8[0xF6DBu] & BIT(7)) == 0u) {
|
|
return;
|
|
}
|
|
if (MEM8[0xF731u] > 3u) {
|
|
return;
|
|
}
|
|
|
|
if ((MEM8[0xF791u] & BIT(5)) == 0u) {
|
|
/* Requests selector 0x0013=0x4000: 00 00 13 40 00 09. */
|
|
/* CCU should ACK 05 00 13 00 00 4C, then mirror 00 00 13 40 00 09. */
|
|
} else {
|
|
/* Requests selector 0x0013=0x0000: 00 00 13 00 00 49. */
|
|
/* CCU should ACK 05 00 13 00 00 4C, then mirror 00 00 13 00 00 49. */
|
|
}
|
|
}
|
|
|
|
void sci1_process_candidate_protocol_command(void)
|
|
{
|
|
u8 command = sci1_rx_candidate_command();
|
|
u16 logical_index = sci1_rx_candidate_logical_index();
|
|
u16 value = sci1_rx_candidate_value();
|
|
|
|
sci1_candidate_panel_selector_annotation(logical_index, value);
|
|
|
|
bool session_active = MEM8[0xFAA2u] != 0u;
|
|
|
|
if (!session_active) {
|
|
/* Initial/idle dispatcher: valid checksum/no RX error, FAA2 == 0. */
|
|
switch (command) {
|
|
case 0x00u:
|
|
/* set_value_acked: candidate write of RX[3:4] into primary/current tables, followed by a response
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0
|
|
* candidate effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
|
* candidate effect: table_write_candidate; target current_value_table_candidate; source same candidate value written to the primary table; table H'E800
|
|
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
|
* evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCB5, H'BCBD, H'BCC5, H'BCCD
|
|
*/
|
|
candidate_set_value_acked(logical_index, value);
|
|
break;
|
|
case 0x01u:
|
|
/* read_value: initial/idle-path primary table read only, followed by an odd response staging sequence
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0 && F861.bit7 == 0
|
|
* note: Only accepted on the initial/idle dispatcher path: valid checksum/no RX error, FAA2 == 0, and F861.bit7 == 0.
|
|
* note: BCD7 stages F850=0x04, writes F851 from F861 and then overwrites F851 from F862.
|
|
* note: BCD7 reads the primary table word at E000 + 2*selector; F854 receives the low byte and F853 receives the high byte.
|
|
* note: F852 is not freshly written in the BCD7 handler, so do not describe the response as a fixed 04 00 QQ hi lo frame.
|
|
* candidate effect: table_read_candidate; target primary_value_table_candidate; table H'E000
|
|
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
|
* evidence: H'BC08, H'BC0C, H'BC24, H'BC26, H'BCD7, H'BCE0, H'BCE8, H'BCF0, H'BCF6, H'BCDC, H'BCE4, H'BCFA
|
|
*/
|
|
if ((RX_FRAME(1) & 0x80u) != 0u) {
|
|
candidate_unknown_command(command, logical_index, value);
|
|
break;
|
|
}
|
|
candidate_read_value(logical_index, value);
|
|
break;
|
|
case 0x02u:
|
|
/* clear_or_abort: candidate clear/abort path with no immediate response builder
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0
|
|
* candidate effect: state_clear_candidate; target serial_session_flags_candidate; clear bit 7; state H'FAA2
|
|
* evidence: H'BC08, H'BC0C, H'BC29, H'BC2B
|
|
*/
|
|
candidate_clear_or_abort(logical_index, value);
|
|
break;
|
|
case 0x07u:
|
|
/* retransmit_or_error_reply: candidate retransmit path; retry/error handling also builds a command 0x07 RX-payload echo
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0 OR valid checksum/no RX physical error && FAA2 != 0
|
|
* note: loc_BE4D is a retry/error echo path: F850=0x07 and F861-F864 are copied into F851-F854 before loc_BA26.
|
|
* note: Observed frame 07 80 40 20 90 2D means RX bytes F861-F864 were 80 40 20 90; it is not a table value.
|
|
* candidate effect: retransmit_candidate; target TX staging bytes H'F850-H'F854 before loc_BA26; source previous TX frame bytes H'F858-H'F85C
|
|
* candidate effect: retry_error_echo_candidate; target F850=0x07, F851-F854=F861-F864 before loc_BA26; source RX payload bytes F861-F864; 07 80 40 20 90 2D echoes RX payload 80 40 20 90; it is not a table value
|
|
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
|
* evidence: H'BC08, H'BC0C, H'BC2E, H'BC30, H'BC54, H'BC56, H'BE09, H'BE11, H'BE19, H'BE22
|
|
*/
|
|
candidate_retransmit_or_error_reply(logical_index, value);
|
|
break;
|
|
default:
|
|
candidate_unknown_command(command, logical_index, value);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Continuation dispatcher: FAA2 != 0. */
|
|
switch (command) {
|
|
case 0x04u:
|
|
/* set_value_no_immediate_reply: candidate write/update path that stores a value without an immediate serial response
|
|
* availability: valid checksum/no RX physical error && FAA2 != 0
|
|
* candidate effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
|
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
|
* evidence: H'BC08, H'BC0C, H'BC45, H'BC47
|
|
*/
|
|
candidate_set_value_no_immediate_reply(logical_index, value);
|
|
break;
|
|
case 0x05u:
|
|
/* ack_or_clear_pending: continuation-only conditional acknowledgement/session clear path
|
|
* availability: valid checksum/no RX physical error && FAA2 != 0
|
|
* note: Only accepted on the continuation dispatcher path when FAA2 != 0.
|
|
* note: For selector 0x0040, frame 05 00 40 00 00 1F performs no response staging.
|
|
* note: The handler clears FAA3/FAA2; F9B5 advances only when FAA2.bit3 was set from a queued report.
|
|
* note: If FAA2 == 0, command 5 falls through the initial dispatcher instead of doing acknowledgement work.
|
|
* candidate effect: conditional_ack_session_clear_candidate; target selected event/pending state; when FAA2 != 0, clear FAA3/FAA2; advance F9B5 only if FAA2.bit3 was set from queued-report state; selector 0x0040 stages no response; selector H'0040 has no response
|
|
* evidence: H'BC08, H'BC0C, H'BC4A, H'BC4C
|
|
*/
|
|
candidate_ack_or_clear_pending(logical_index, value);
|
|
break;
|
|
case 0x06u:
|
|
/* set_secondary_value: candidate secondary-table value write path
|
|
* availability: valid checksum/no RX physical error && FAA2 != 0
|
|
* candidate effect: table_write_candidate; target secondary_value_table_candidate; source RX[3:4] value bytes; table H'E400
|
|
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 6; table H'EC00
|
|
* evidence: H'BC08, H'BC0C, H'BC4F, H'BC51
|
|
*/
|
|
candidate_set_secondary_value(logical_index, value);
|
|
break;
|
|
case 0x07u:
|
|
/* retransmit_or_error_reply: candidate retransmit path; retry/error handling also builds a command 0x07 RX-payload echo
|
|
* availability: valid checksum/no RX physical error && FAA2 == 0 OR valid checksum/no RX physical error && FAA2 != 0
|
|
* note: loc_BE4D is a retry/error echo path: F850=0x07 and F861-F864 are copied into F851-F854 before loc_BA26.
|
|
* note: Observed frame 07 80 40 20 90 2D means RX bytes F861-F864 were 80 40 20 90; it is not a table value.
|
|
* candidate effect: retransmit_candidate; target TX staging bytes H'F850-H'F854 before loc_BA26; source previous TX frame bytes H'F858-H'F85C
|
|
* candidate effect: retry_error_echo_candidate; target F850=0x07, F851-F854=F861-F864 before loc_BA26; source RX payload bytes F861-F864; 07 80 40 20 90 2D echoes RX payload 80 40 20 90; it is not a table value
|
|
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
|
* evidence: H'BC08, H'BC0C, H'BC2E, H'BC30, H'BC54, H'BC56, H'BE09, H'BE11, H'BE19, H'BE22
|
|
*/
|
|
candidate_retransmit_or_error_reply(logical_index, value);
|
|
break;
|
|
default:
|
|
candidate_unknown_command(command, logical_index, value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* TX reconstruction evidence
|
|
* candidate/evidence-supported SCI1 6-byte TX frame hypothesis using buffer H'F858-H'F85D with checksum byte H'F85D seeded by H'005A
|
|
* checksum formula: checksum = 0x5A ^ byte0 ^ byte1 ^ byte2 ^ byte3 ^ byte4
|
|
* evidence addresses:
|
|
* - checksum_byte: H'BA64
|
|
* - initial_send_from_buffer_start: H'BA6E, H'BA72
|
|
* - tx_buffer_region: H'BA3A, H'BA42, H'BA4A, H'BA50, H'BA54, H'BA58, H'BA5C, H'BA60, H'BA64, H'BA6E, H'BE05, H'BE0D, H'BE15
|
|
* - tx_checksum_seed: H'BA4E
|
|
* - tx_index_compare_frame_length: H'BAC3
|
|
* - tx_index_increment: H'BABF
|
|
* - tx_index_initialized_to_one: H'BA76
|
|
* - tx_isr_indexed_send: H'BAAB, H'BAB1, H'BAB5
|
|
* - xor_checksum_chain: H'BA50, H'BA54, H'BA58, H'BA5C, H'BA60, H'BA64
|
|
*/
|
|
static u8 sci1_tx_candidate_checksum(void)
|
|
{
|
|
u8 checksum = 0x5Au;
|
|
checksum ^= TX_FRAME(0);
|
|
checksum ^= TX_FRAME(1);
|
|
checksum ^= TX_FRAME(2);
|
|
checksum ^= TX_FRAME(3);
|
|
checksum ^= TX_FRAME(4);
|
|
return checksum;
|
|
}
|
|
|
|
void sci1_tx_start_candidate_frame(void)
|
|
{
|
|
/* The ROM appears to have populated TX_FRAME(0..4) before this point. */
|
|
TX_FRAME(5) = sci1_tx_candidate_checksum();
|
|
|
|
while ((SCI1_SSR & SCI_SSR_TDRE) == 0u) {
|
|
/* wait for transmit data register empty */
|
|
}
|
|
|
|
/* First byte is sent synchronously; TIE enables TXI for the remaining bytes. */
|
|
SCI1_TDR = TX_FRAME(0);
|
|
TX_INDEX = 1u;
|
|
SCI1_SSR &= (u8)~SCI_SSR_TDRE;
|
|
SCI1_SCR |= SCI_SCR_TIE;
|
|
}
|
|
|
|
void sci1_txi_candidate_isr(void)
|
|
{
|
|
/* TXI runs after hardware reasserts SSR.TDRE for the next transmit byte. */
|
|
if ((SCI1_SSR & SCI_SSR_TDRE) == 0u) {
|
|
return;
|
|
}
|
|
|
|
if (TX_INDEX < TX_FRAME_LENGTH) {
|
|
SCI1_TDR = TX_FRAME(TX_INDEX);
|
|
TX_INDEX = (u8)(TX_INDEX + 1u);
|
|
SCI1_SSR &= (u8)~SCI_SSR_TDRE;
|
|
}
|
|
|
|
if (TX_INDEX >= TX_FRAME_LENGTH) {
|
|
SCI1_SCR &= (u8)~SCI_SCR_TIE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* RX reconstruction evidence
|
|
* candidate/evidence-supported SCI1 6-byte RX frame hypothesis using capture buffer H'F868-H'F86D; checksum byte H'F865 is validated against XOR seeded by H'005A
|
|
* checksum formula: checksum = 0x5A ^ byte0 ^ byte1 ^ byte2 ^ byte3 ^ byte4
|
|
* RX error handling: SCI1 ERI appears to mark a physical receive error and continue into the RXI byte-capture path; the RXI path clears RDRF before reading RDR in the ROM order.
|
|
* RX error caveat: Manual text distinguishes ORER from FER/PER data transfer into RDR and describes the normal RDR-read then RDRF-clear ordering; this output preserves the observed ROM order.
|
|
* evidence addresses:
|
|
* - rx_checksum_seed: H'BBD6
|
|
* - rx_complete_timer: H'BB9E
|
|
* - rx_copy_capture_to_frame_buffer: H'BBB3, H'BBBB, H'BBC3, H'BBB7, H'BBBF, H'BBC7
|
|
* - rx_eri_falls_through_to_rxi: H'BB57, H'BB5B, H'BB5F, H'BB63, H'BB69, H'BB6D
|
|
* - rx_index_increment_store: H'BB94, H'BB96
|
|
* - rx_indexed_store: H'BB90
|
|
* - rx_isr_compare_frame_length: H'BB9A
|
|
* - rx_processor_requires_six_bytes: H'BBAB
|
|
* - rx_rdr_read: H'BB6D
|
|
* - rx_rdrf_clear_before_rdr_read: H'BB69, H'BB6D
|
|
* - rx_xor_checksum_validation: H'BBD6, H'BBD8, H'BBDC, H'BBE0, H'BBE4, H'BBE8, H'BBEC
|
|
*/
|
|
static u8 sci1_rx_candidate_checksum(void)
|
|
{
|
|
u8 checksum = 0x5Au;
|
|
checksum ^= RX_FRAME(0);
|
|
checksum ^= RX_FRAME(1);
|
|
checksum ^= RX_FRAME(2);
|
|
checksum ^= RX_FRAME(3);
|
|
checksum ^= RX_FRAME(4);
|
|
return checksum;
|
|
}
|
|
|
|
bool sci1_process_rx_candidate_frame(void)
|
|
{
|
|
u8 i;
|
|
|
|
if (RX_INDEX != RX_FRAME_LENGTH) {
|
|
return false;
|
|
}
|
|
|
|
for (i = 0u; i < RX_FRAME_LENGTH; i++) {
|
|
RX_FRAME(i) = RX_CAPTURE(i);
|
|
}
|
|
|
|
if (sci1_rx_candidate_checksum() != RX_FRAME(5)) {
|
|
RX_INDEX = 0u;
|
|
return false;
|
|
}
|
|
|
|
RX_INDEX = 0u;
|
|
return true;
|
|
}
|
|
|
|
bool sci1_rx_byte_received_candidate_isr(void)
|
|
{
|
|
u8 byte;
|
|
|
|
SCI1_SSR &= (u8)~SCI_SSR_RDRF;
|
|
byte = SCI1_RDR;
|
|
|
|
if (RX_INTERBYTE_TIMEOUT == 0u) {
|
|
RX_INDEX = 0u;
|
|
}
|
|
|
|
RX_INTERBYTE_TIMEOUT = 5u;
|
|
RX_CAPTURE(RX_INDEX) = byte;
|
|
RX_INDEX = (u8)(RX_INDEX + 1u);
|
|
|
|
if (RX_INDEX == RX_FRAME_LENGTH) {
|
|
RX_COMPLETE_TIMER = 0x14u;
|
|
return sci1_process_rx_candidate_frame();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void sci1_rx_error_candidate_isr(void)
|
|
{
|
|
RX_ERROR_LATCH |= RX_ERROR_LATCH_PHYSICAL_ERROR;
|
|
SCI1_SSR &= (u8)~(SCI_SSR_ORER | SCI_SSR_FER | SCI_SSR_PER);
|
|
sci1_rx_byte_received_candidate_isr();
|
|
}
|