blob: a058fd7dc70458af4d387e4feef82d017b6e0421 [file] [log] [blame] [edit]
#include <Arduino.h>
#include <SPI.h>
#include "gonk/pin_config.h"
#include "stm32f7xx_hal_qspi.h"
#define PW_LOG_LEVEL PW_LOG_LEVEL_DEBUG
#define PW_LOG_MODULE_NAME "PinConfig"
#include "pw_log/log.h"
namespace {
volatile uint8_t gpio1_assert_ = 0;
volatile uint8_t gpio2_assert_ = 0;
volatile uint8_t gpio3_assert_ = 0;
volatile uint8_t gpio6_assert_ = 0;
void Gpio1Interrupt() {
gpio1_assert_ = 1;
PW_LOG_INFO("Header pin assert: 1");
}
void Gpio2Interrupt() {
gpio2_assert_ = 1;
PW_LOG_INFO("Header pin assert: 2");
}
void Gpio3Interrupt() {
gpio3_assert_ = 1;
PW_LOG_INFO("Header pin assert: 3");
}
void Gpio6Interrupt() {
gpio6_assert_ = 1;
PW_LOG_INFO("Header pin assert: 6");
}
} // namespace
namespace gonk::pin_config {
PinConfig::PinConfig()
: fpga_spi(FpgaDspiMOSI, FpgaDspiMISO, FpgaDspiCLK, FpgaDspiCS) {
flash_spi = SPIClass(FlashMOSI, FlashMISO, FlashCLK);
}
void PinConfig::Init() {
// Set STATUS LED mode and initial state.
pinMode(StatusLed, OUTPUT);
digitalWrite(StatusLed, LOW);
// Default CS pin to output high.
pinMode(FlashCS, OUTPUT);
digitalWrite(FlashCS, HIGH);
// Top header GPIO inputs.
pinMode(HeaderPin1, INPUT_PULLUP);
pinMode(HeaderPin2, INPUT_PULLUP);
pinMode(HeaderPin3, INPUT_PULLUP);
pinMode(HeaderPin6, INPUT_PULLUP);
attachInterrupt(/*pin=*/HeaderPin1,
/*callback=*/&Gpio1Interrupt,
/*mode=*/LOW);
attachInterrupt(/*pin=*/HeaderPin2,
/*callback=*/&Gpio2Interrupt,
/*mode=*/LOW);
attachInterrupt(/*pin=*/HeaderPin3,
/*callback=*/&Gpio3Interrupt,
/*mode=*/LOW);
attachInterrupt(/*pin=*/HeaderPin6,
/*callback=*/&Gpio6Interrupt,
/*mode=*/LOW);
}
void PinConfig::InitFpgaPins() {
// Set FPGA reset pin mode and initial state.
pinMode(ICE40ResetN, OUTPUT);
digitalWrite(ICE40ResetN, HIGH);
// Set FPGA configure done signal pin as an input.
pinMode(ICE40Done, INPUT);
// FPGA Application IO pins
pinMode(FpgaIoReset, OUTPUT);
digitalWrite(FpgaIoReset, LOW);
pinMode(FpgaIoMode, OUTPUT);
digitalWrite(FpgaIoMode, LOW);
pinMode(FpgaIoValid, INPUT);
InitSampleBus();
}
void PinConfig::InitSampleBus() { fpga_spi.begin(); }
void PinConfig::FpgaHalt() {
// Set FlashCS to signal the FPGA it should load the bitstream from external
// flash.
pinMode(FlashCS, INPUT_FLOATING);
delay(10);
// Hold in reset for a small amount of time.
digitalWrite(ICE40ResetN, LOW);
delay(50);
// Boot fpga and give it time to reset any internal SPI pin configuration.
digitalWrite(ICE40ResetN, HIGH);
delay(10);
// Finally, hold in reset.
digitalWrite(ICE40ResetN, LOW);
}
void PinConfig::FpgaSpiConfigMode() {
// Turn on Flash Hold so it ignores any SPI communication.
pinMode(FlashHold, OUTPUT);
pinMode(FlashWP, OUTPUT);
digitalWrite(FlashHold, LOW);
digitalWrite(FlashWP, LOW);
delay(1);
// Set FlashCS (ICE_SPI_SS) low and pulse ICE40ResetN. This signals the FPGA
// to boot into SPI config mode.
pinMode(ICE40ResetN, OUTPUT);
pinMode(FlashCS, OUTPUT);
// Pulse ICE40ResetN
digitalWrite(ICE40ResetN, LOW);
digitalWrite(FlashCS, LOW);
delay(10);
digitalWrite(ICE40ResetN, HIGH);
// Enalble GPIO control of MOSI, MISO and CLK.
pinMode(FlashMOSI, OUTPUT);
pinMode(FlashMISO, OUTPUT);
pinMode(FlashCLK, OUTPUT);
delay(1);
// Send 8 clock pulses.
for (int i = 0; i < 8; i++) {
digitalWrite(FlashCLK, LOW);
delayMicroseconds(100);
digitalWrite(FlashCLK, HIGH);
delayMicroseconds(100);
}
delay(10);
}
void PinConfig::FpgaEnable() { digitalWrite(ICE40ResetN, HIGH); }
void PinConfig::SPIEnable() {
// Disable Flash hold and write protect.
pinMode(FlashHold, OUTPUT);
pinMode(FlashWP, OUTPUT);
digitalWrite(FlashHold, HIGH);
digitalWrite(FlashWP, HIGH);
}
void PinConfig::SPIDisable() {
pinMode(FlashCS, OUTPUT);
pinMode(FlashCLK, OUTPUT);
pinMode(FlashMOSI, OUTPUT);
pinMode(FlashMISO, INPUT_FLOATING);
digitalWrite(FlashCS, HIGH);
digitalWrite(FlashCLK, HIGH);
digitalWrite(FlashMOSI, HIGH);
}
void PinConfig::ClearGpioInterrupts() {
gpio1_assert_ = 0;
gpio2_assert_ = 0;
gpio3_assert_ = 0;
gpio6_assert_ = 0;
}
} // namespace gonk::pin_config