#include "build/sh1107.h" #include <iostream> /** * Yawonk. */ extern "C" const uint8_t *spi_flash_content; extern "C" uint32_t spi_flash_base; extern "C" uint32_t spi_flash_length; namespace cxxrtl_design { struct bb_p_spifr__whitebox_impl : public bb_p_spifr__whitebox { enum { STATE_IDLE, STATE_SELECTED_POWER_DOWN, STATE_SELECTED_POWERING_UP_NEEDS_DESELECT, STATE_DESELECTED_POWERED_UP, STATE_SELECTED_POWERED_UP, STATE_READING } state; uint32_t sr; uint8_t edges; uint32_t addr; uint8_t bit; void reset() override { this->state = STATE_IDLE; this->sr = 0u; this->edges = 0u; this->addr = 0u; this->bit = 0u; p_cipo = wire<1>{0u}; } bool eval(performer *performer) override { bool converged = true; bool posedge_p_clk = this->posedge_p_clk(); if (posedge_p_clk) { p_cipo.next = value<1>{0u}; uint32_t srnext = ((this->sr & 0x7fffffffu) << 1) | p_copi.get<uint32_t>(); switch (this->state) { case STATE_IDLE: { if (p_cs) { this->state = STATE_SELECTED_POWER_DOWN; } break; } case STATE_SELECTED_POWER_DOWN: { if (this->edges == 7 && (srnext & 0xffu) == 0xabu) { this->state = STATE_SELECTED_POWERING_UP_NEEDS_DESELECT; } break; } case STATE_SELECTED_POWERING_UP_NEEDS_DESELECT: { if (!p_cs) { this->state = STATE_DESELECTED_POWERED_UP; } break; } case STATE_DESELECTED_POWERED_UP: { if (p_cs) { this->state = STATE_SELECTED_POWERED_UP; } break; } case STATE_SELECTED_POWERED_UP: { if (this->edges == 31u && (srnext >> 24) == 0x03u) { this->addr = srnext & 0x00ffffffu; this->state = STATE_READING; // fallthrough } else { break; } } case STATE_READING: { if (this->addr >= spi_flash_base && this->addr < spi_flash_base + spi_flash_length) { uint8_t bit = (spi_flash_content[this->addr - spi_flash_base] >> (7 - this->bit)) & 0x1; if (++this->bit == 8) { this->bit = 0; ++this->addr; } p_cipo.next = value<1>{bit}; } if (!p_cs) { this->state = STATE_IDLE; } break; } } if (p_cs) { this->sr = srnext; ++this->edges; } else { this->edges = 0; } } return converged; } }; std::unique_ptr<bb_p_spifr__whitebox> bb_p_spifr__whitebox::create(std::string name, metadata_map parameters, metadata_map attributes) { return std::make_unique<bb_p_spifr__whitebox_impl>(); } } // namespace cxxrtl_design