astuder / Inside-EZRadioPRO

Reverse engineering the Silabs EZRadioPRO family of sub-GHz radios
MIT License
53 stars 10 forks source link

ACFG registers Read/Write issue #3

Open rep-stosw opened 8 months ago

rep-stosw commented 8 months ago

Can not read and write ACFG registers via SFR-register:

SFRout(0x93,0x41); //enable load

static u8 ACFGin(u8 address) //read ACFG reg
{
 SFRout(0x94,address);
 return SFRin(0x95);
}

static void ACFGout(u8 address,u8 data) //write ACFG reg
{
 SFRout(0x94,address);
 SFRout(0x95,data);
}

Register Window not working... Permanently read 0x58 from any ACFG register.

I use i8051 code for access SFR:

.module SFRin

.area CSEG (ABS, CODE)
.org 0x0488

    mov R0,#0x71
    movx    A,@R0       ;A=[0x5071]=CMDBuf[1]=address

    mov DPTR,#SFR
    movx    @DPTR,A     ;[SFR]=A

    .db 0xE5        ;mov A,_byte_(SFR)
SFR:    .db     0x00

    mov R0,#0x70
    movx    @R0,A       ;[0x5070]=A=Reg CMDBuf[1]

    ret

.module SFRout

.area CSEG (ABS, CODE)
.org 0x0488

    mov R0,#0x71
    movx    A,@R0       ;A=[0x5071]=CMDBuf[1]=address

    mov DPTR,#SFR
    movx    @DPTR,A     ;[SFR]=A

    mov R0,#0x72
    movx    A,@R0       ;A=[0x5072]=CMDBuf[2]=data

    .db 0xF5        ;mov _byte_(SFR),A
SFR:    .db     0x00

    ret

Please, help. How ACFG can be read/written?

astuder commented 8 months ago

Happy to see that someone else is digging into the EZRadioPRO :)

I assume, you already verified that your patch runs on the EZRadioPRO, for example via a hard-coded response.

I never experimented with the ACFG registers myself. One possibility is, that they are write-only. The EZRadioPRO firmware maintains a cache of data written to the ACFG registers at 0x0798 - 0x07ef. For the PEEK API command, this data is mapped to the address 0xe000.

See: https://github.com/astuder/Inside-EZRadioPRO/blob/master/docs/api/cmd-peek.md

I should document the address mapping for POKE one of these days.. it's slightly different but IIRC also has a range that writes to the ACFG registers.

astuder commented 8 months ago

FWIW, the firmware during boot writes to ACFG like this:

void boot.acfg_write(byte data,ACFG_ADDR_T addr)
{
  ACFG_ADDR = addr;
  ACFG_DATA = data;
  ACFG_CTRL = ACFG_LOAD_EN|ACFG_reserved1|AUTO_LOAD_EN;
  return;
}

but then later during power_up:

void rom.init_acfg_xpage(void)
{
  ACFG_CTRL = AUTO_LOAD_EN;
  XPAGE = 0x50;
  return;
}

Based on cross references in Ghidra, there are a few occasions of read access to ACFG_DATA. For example this one that may be related to power amplifier sequencing:

        RAM:c0e0 e4              CLR        A
        RAM:c0e1 ff              MOV        R7,A
                             LAB_RAM_c0e2                                    XREF[2]:     RAM:c0d8 (j) , RAM:c0ed (j)   
        RAM:c0e2 ec              MOV        A,R4
        RAM:c0e3 24  fe           ADD        A,#0xfe
        RAM:c0e5 fb              MOV        R3,A
                             LAB_RAM_c0e6                                    XREF[1]:     RAM:c0e6 (j)   
        RAM:c0e6 db  fe           DJNZ       R3,LAB_RAM_c0e6                                  ;wait for SEQ_DELAY .1us
        RAM:c0e8 ed              MOV        A,R5
        RAM:c0e9 25  95           ADD        A,ACFG_DATA                                      = ??
        RAM:c0eb f5  95           MOV        ACFG_DATA ,A                                     = ??
        RAM:c0ed de  f3           DJNZ       R6,LAB_RAM_c0e2
        RAM:c0ef 8f  95           MOV        ACFG_DATA ,R7                                    = ??
        RAM:c0f1 00              NOP

So there's some hope...

astuder commented 8 months ago

Another thought: Looks like you are executing two separate SPI commands SFRout(ACFG_ADDR), and then SFRin(ACFG_DATA). Maybe the EZRadioPRO accesses ACFG between the two SPI commands, changing ACFG_ADDR. To ensure that you are addressing the correct ACFG register, you probably should do both steps in one SPI command.

rep-stosw commented 8 months ago

Thanks for the help! Later, I actually did to write 2 functions: reading and writing to the ACFG registers.

It appears that only writing to these registers works. Because writing to some registers causes the RFIC Si4463 to hang.

I'm trying to configure a Si4463 to output I and Q signals(from PGA or Mixer) to the GPIO. Do you think this is possible?

Registers: PGA_PGA_TEST and PGA_PGA_TEST_DIFF.

But I can't hear anything from GPIO0 output. While I connected the amplifier - with the GPIO function 20,21 and 31 (not documented) I hear a bitstream. Later, I recorded the signal in Audacity (sampling frequency 5 MHz, this is 2-3 seconds without freezing the PC).

I also tried to increase the size of the TX/RX FIFO. 1.5 times. But when trying to execute the RX command, FIFO Overflow is caused. Perhaps the Packet handler has limitations in the code.

My goal: 1 Mbps bit rate (4GFSK). Improve communication quality. Is it possible to extract soft decisions from the demodulator instead of hard decisions? For LDPC or Turbo codes in FEC?

astuder commented 7 months ago

I haven't experimented much with the GPIO settings. Interesting about the bit stream with the undocumented settings. A binary dump might be more useful than audio samples.

Getting IQ out of the radio would definitely be cool, though I'd be more interested in the IQ samples rather than the analog signal.

A potentially related feature outputs "phase samples" through the RX FIFO. See MODEM_MDM_CTRL FIFO_SRC_SEL in the public API documentation. Internally, this interacts with the SFR PHASE_OUT, and I think it's a signed 7-bit number. Unfortunately, I didn't find any detailed documentation of that feature.

But we're getting a bit off-topic on the ACFG register issue :) You are welcome to contact me by email (see my profile) if you'd like to discuss further.