#include "string.h"
#include "norflash.h"

/// Enumerace povelů pro SPI FLASH.
enum FLASH_COMMANDS : uint8_t {
  /* single byte commands */
  FLASH_WRDI = 0x04,    // nepoužito
  FLASH_WREN = 0x06,
  FLASH_RDID = 0x9F,
  FLASHRSTEN = 0x66,    // nepoužito
  FLASH__RST = 0x99,    // nepoužito
  FLASH__RES = 0xAB,    // release from power down, nepoužito
  FLASH__DPD = 0xB9,    // power down, nepoužito
  // multi - byte
  FLASH_RDSR1 = 0x05,
  // dále se mohou povely lišit
  FLASH_RDSR2 = 0x35,   // nepoužito
  FLASH_4READ = 0x03,
  FLASH_4PP   = 0x02,
  FLASH_4SE   = 0x20,
};
union FlashCommandHeader {
  struct {
    FLASH_COMMANDS cmd : 8;
    uint32_t       adr : 24;       // adresa je BIG ENDIEN - vyšší byte vystupuje po SPI dříve (MSB FIRST).
  }__attribute__((packed));
  uint8_t bytes [4];
}__attribute__((packed));
static inline uint32_t be_set_24 (const uint32_t p) {
  return  ((p & 0x000000ff) << 16)
        | ((p & 0x0000ff00) <<  0)
        | ((p & 0x00ff0000) >> 16);
}
/* Nic jiného zatím není potřeba, ale šlo by dodělat i zápis včetně mazání bloku.
*/
unsigned int NorFlash::ReadBlock(const unsigned int addr, uint8_t * data, const unsigned int len) {
  FlashCommandHeader header;
  header.cmd = FLASH_4READ;
  header.adr = be_set_24(addr);
  spi.ChipSelect(true);
  for (unsigned n=0u; n<sizeof(header); n++) spi.ReadWriteByte(header.bytes[n]);
  for (unsigned n=0u; n<len; n++) data [n] = spi.ReadWriteByte(0xff);
  spi.ChipSelect(false);
  return len;
}