ADE9000 readout problem

I am using the ADE9000 with sinc4+iir as the source for waveform buffer.

Whenever I read out the first sample of a new page of the buffer, the sign extension isn't coming out properly.

As you might recall from the ADE9000 datasheet, the sinc4+iir has the ADC data shifted left by 4 bits and sign extended to make the data 32-bit.

The data that is read out is wrong, and this is only seen in 'IA' (current from phase/line A) from the waveform buffer (as it is the first sample that is read out from the buffer).

When the current goes into its negative cycle and a new page is read, the sign extension messes up. 

For example if the data is supposed to be -103504 (11111111111111100110101110110000 in binary), the data that is read out is 16673712 (00000000111111100110101110110000 in binary).

This only happens when the new page starts in the negative cycle of the current of line A.

I am not manipulating any bits in any way.. and also, the rest of the data is absolutely spot on.

The faulty data is also confirmed to be read out properly from the ADE9000 as the last 4 bits are always 0000, as mentioned in the datasheet.

What I mean to say is, I can't find any fault in the code that I have used.

Does anyone have a solution for this?

The main function calls these 2 functions. The code of which is shared below.'

union {
uint8_t read_wbf[24];
int32_t read_val[14];
} converted_wbf;

//main function calls these once in setup()//

take_all_readings_wbf();
read_wbf_pages();

//main function ends//

#define FLASH_PAGE_SIZE  256
#define BURST_READ_LEN 384
#define READ_BYTES 512
#define TOTAL_READ_PAGES (MEMORY_SIZE_IN_BYTES_WBF / READ_BYTES)

static inline byte take_all_readings_wbf() {
uint32_t status0 = 0;
uint16_t wfb_last_page_filled, wfb_last_page_read;
uint16_t wbf_address;
SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE0));
ade9000.SPI_Write_32(ADDR_STATUS0, 0x20000); // CLEAR INTERRUPTS, WRITE 0x20000 TO STATUS0
Serial.print("Start wbf filling with WFB_CFG: ");
uint16_t wfb_cfg_register = ade9000.SPI_Read_16(ADDR_WFB_CFG);
bitSet(wfb_cfg_register, 4);
ade9000.SPI_Write_16(ADDR_WFB_CFG, wfb_cfg_register);
Serial.println(ade9000.SPI_Read_16(ADDR_WFB_CFG), HEX);
Serial.print(micros());
Serial.println(" us");
while (1) {
status0 = ade9000.SPI_Read_32(ADDR_STATUS0);
// IS PAGE FULL INTERRUPT (BIT 17 IN STATUS0) TRUE?
if (bitRead(status0, 17) == true) {
wfb_last_page_filled = ade9000.SPI_Read_16(ADDR_WFB_TRG_STAT) >> 12;
if (wfb_last_page_read != wfb_last_page_filled) {
if (wfb_last_page_filled == 0) {
wbf_address = 0x8008;
} else {
wbf_address += 2048;
}
SPI_Burst_Read_Wfb(wbf_address);
store_wfb_all_ch();
wfb_last_page_read = wfb_last_page_filled;
}
}
if (address >= WFB_BYTES_TEST) // TODO MEMORY_SIZE_IN_BYTES_WBF
break;
}
Serial.print(micros());
Serial.println(" us Stoped filling WBF");
wfb_cfg_register = ade9000.SPI_Read_16(ADDR_WFB_CFG);
bitClear(wfb_cfg_register, 4);
ade9000.SPI_Write_16(ADDR_WFB_CFG, wfb_cfg_register);
}

static inline byte SPI_Burst_Read_Wfb(uint16_t wbf_address) {
digitalWrite(CS_ADE, LOW);
SPI.transfer16(wbf_address); //Send the starting address
for (int i = 0; i < BURST_READ_LEN; i++)
{
buffer_wfb[i] = SPI.transfer(0);
}
digitalWrite(CS_ADE, HIGH);
}

static inline byte store_wfb_all_ch() {
for (uint8_t i = 0; i < 2; i++) {
SPI_write_enable(); //SPI write enable need to execute every flash page write instruction
flash_page_write_allch(address, buffer_wfb, i*256);
address += FLASH_PAGE_SIZE;
while (check_flash_busy());
}
}

static inline byte SPI_write_enable() {
digitalWrite(CS_flash, LOW);
SPI.transfer(SPIFLASH_WRITEENABLE);
digitalWrite(CS_flash, HIGH);
}

static inline byte flash_page_write_allch(uint32_t addr, const uint8_t* buf, uint16_t index) {
digitalWrite(CS_flash, LOW);
SPI.transfer(SPIFLASH_BYTEPAGEPROGRAM);
SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8);
SPI.transfer(addr);
for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) {
if ((index == 384))
return 0;
SPI.transfer(buf[index]);
index++;
}
digitalWrite(CS_flash, HIGH);
}

static inline byte read_wbf_pages() {
Serial.println("wbf reading started from flash");
for (byte i = 0; i < TOTAL_READ_PAGES; i++) {
ext_memory_read_bytes(read_address);
read_address += READ_BYTES;
if (read_address >= MEMORY_SIZE_IN_BYTES_WBF) {
Serial.println("wbf reading from flash done");
break;
}
}
}

byte ext_memory_read_bytes(uint32_t read_addr) {
uint8_t read_buff[READ_BYTES];
memset(read_buff, 0, sizeof(read_buff));
flash_page_read(read_addr, read_buff, READ_BYTES);
while (check_flash_busy());
for (int i = 0; i < READ_BYTES; i = i + 24)
{
if ((i == 384))
return 0;
memset(converted_wbf.read_val, 0, sizeof(converted_wbf.read_val));
converted_wbf.read_wbf[3] = read_buff[i];
converted_wbf.read_wbf[2] = read_buff[i + 1];
converted_wbf.read_wbf[1] = read_buff[i + 2];
converted_wbf.read_wbf[0] = read_buff[i + 3];
Serial.print(converted_wbf.read_val[0], DEC); // Print IA readings value
Serial.print(",");
converted_wbf.read_wbf[3] = read_buff[i + 4];
converted_wbf.read_wbf[2] = read_buff[i + 5];
converted_wbf.read_wbf[1] = read_buff[i + 6];
converted_wbf.read_wbf[0] = read_buff[i + 7];
Serial.print(converted_wbf.read_val[0], DEC); // Print VA readings value
Serial.print(",");
converted_wbf.read_wbf[3] = read_buff[i + 8];
converted_wbf.read_wbf[2] = read_buff[i + 9];
converted_wbf.read_wbf[1] = read_buff[i + 10];
converted_wbf.read_wbf[0] = read_buff[i + 11];
Serial.print(converted_wbf.read_val[0], DEC); // Print IB readings value
Serial.print(",");
converted_wbf.read_wbf[3] = read_buff[i + 12];
converted_wbf.read_wbf[2] = read_buff[i + 13];
converted_wbf.read_wbf[1] = read_buff[i + 14];
converted_wbf.read_wbf[0] = read_buff[i + 15];
Serial.print(converted_wbf.read_val[0], DEC); // Print VB readings value
Serial.print(",");
converted_wbf.read_wbf[3] = read_buff[i + 16];
converted_wbf.read_wbf[2] = read_buff[i + 17];
converted_wbf.read_wbf[1] = read_buff[i + 18];
converted_wbf.read_wbf[0] = read_buff[i + 19];
Serial.print(converted_wbf.read_val[0], DEC); // Print IC readings value
Serial.print(",");
converted_wbf.read_wbf[3] = read_buff[i + 20];
converted_wbf.read_wbf[2] = read_buff[i + 21];
converted_wbf.read_wbf[1] = read_buff[i + 22];
converted_wbf.read_wbf[0] = read_buff[i + 23];
Serial.print(converted_wbf.read_val[0], DEC); // Print VC readings value
Serial.println("");
}
}

static inline byte flash_page_read(uint32_t addr, uint8_t* buf, uint16_t len) {
digitalWrite(CS_flash, LOW);
SPI.transfer(SPIFLASH_ARRAYREAD);
SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8);
SPI.transfer(addr);
for (uint16_t i = 0; i < len; ++i)
buf[i] = SPI.transfer(0);
digitalWrite(CS_flash, HIGH);
}