summaryrefslogtreecommitdiff
path: root/sw/Core/Src/spi.h
diff options
context:
space:
mode:
authorStijn Kuipers <stijnkuipers@gmail.com>2023-06-29 16:26:07 +0200
committerStijn Kuipers <stijnkuipers@gmail.com>2023-06-29 16:26:07 +0200
commitfb5a321dd7c2848128b04b306f3e1e59c87a3f70 (patch)
treea8ef6273f9f331ebb1971a9baf20a8c897955612 /sw/Core/Src/spi.h
parentbae7568fd4dd0676b370be8548c7ec95d6521ba1 (diff)
downloadplinky-fb5a321dd7c2848128b04b306f3e1e59c87a3f70.tar.gz
Initial Filedump
Tadaaa!!
Diffstat (limited to 'sw/Core/Src/spi.h')
-rwxr-xr-xsw/Core/Src/spi.h443
1 files changed, 443 insertions, 0 deletions
diff --git a/sw/Core/Src/spi.h b/sw/Core/Src/spi.h
new file mode 100755
index 0000000..9affd1f
--- /dev/null
+++ b/sw/Core/Src/spi.h
@@ -0,0 +1,443 @@
+#define AVG_GRAINBUF_SAMPLE_SIZE 68 // 2 extra for interpolation, 2 extra for SPI address at the start
+#define GRAINBUF_BUDGET (AVG_GRAINBUF_SAMPLE_SIZE*32)
+#define MAX_SPI_STATE 32
+
+#define MAX_SAMPLE_LEN (1024*1024*2) // max sample length in samples
+
+int grainpos[32];
+s16 grainbuf[GRAINBUF_BUDGET];
+s16 grainbufend[32]; // for each of the 32 grain fetches, where does it end in the grainbuf?
+u8 spibigtx[256 + 4];
+u8 spibigrx[256 + 4];
+#define EXPANDER_ZERO 0x800
+#define EXPANDER_RANGE 0x7ff
+#define EXPANDER_MAX 0xfff
+u16 expander_out[4] = { EXPANDER_ZERO,EXPANDER_ZERO,EXPANDER_ZERO,EXPANDER_ZERO };
+
+int spi_readgrain_dma(int gi);
+volatile u8 spistate=0;
+u32 startspi;
+u8 alexdmamode;
+volatile u32 spiduration;
+volatile u8 dummy;
+static inline void spidelay(void) {
+ for (int i = 0; i < 10; ++i) dummy++;
+
+}
+
+void resetspistate(void) {
+ spistate = 0;
+ spiduration = RDTSC() - startspi;
+ alexdmamode = 0;
+#ifndef EMU
+ GPIOA->BSRR = 1<<8; // DAC cs high
+#endif
+}
+
+void spi_update_dac(int dacchan);
+
+
+void spi_read_done(void) {
+ if (spistate >= MAX_SPI_STATE) {
+#ifndef EMU
+ GPIOA->BSRR = 1<<8; // DAC cs high
+#endif
+ if (spistate == MAX_SPI_STATE+4) {
+ resetspistate();
+ } else {
+ int dacchan = spistate-MAX_SPI_STATE;
+ spi_update_dac(dacchan);
+ }
+ }
+ else {
+ spi_readgrain_dma(spistate);
+ }
+}
+
+#ifdef EMU
+extern s16 _flashram[8 * MAX_SAMPLE_LEN];
+s16 _flashram[8* MAX_SAMPLE_LEN];
+#ifndef WASM
+FILE* flashfile = 0;
+#endif
+void spi_wait(void){}
+int spi_writeenable(void) { return 0; }
+int spi_readid(void) { return 0; }
+void spi_setchip(uint32_t addr) {}
+int spi_waitnotbusy(const char *msg, void(*callback)(void)) { return 0; }
+int spi_erase64k(u32 addr, void (*callback)(void)) {
+ memset(_flashram + addr / 2, -1, 65536);
+#ifndef WASM
+ if (flashfile) {
+ fseek(flashfile, addr, 0);
+ fwrite(_flashram + addr / 2, 1, 65536, flashfile);
+ fflush(flashfile);
+ }
+#endif
+ for (int i = 0; i < 16; ++i) {
+ HAL_Delay(2);
+ if (callback) callback();
+ }
+ return 0;
+}
+void spiopen(void) {
+#ifndef WASM
+ if (!flashfile) {
+ flashfile = fopen("flashspi.raw", "r+b");
+ if (!flashfile) {
+ flashfile = fopen("flashspi.raw", "wb");
+ if (flashfile) {
+ u8 zero[1024] = {0};
+ for (int i = 0; i < (MAX_SAMPLE_LEN*16)/1024; ++i)
+ fwrite(zero, 1, 1024, flashfile);
+ fclose(flashfile);
+ flashfile = fopen("flashspi.raw", "r+b");
+ }
+ }
+ if (flashfile) {
+ fseek(flashfile, 0, 0);
+ fread(_flashram, 16, MAX_SAMPLE_LEN, flashfile);
+ }
+ }
+#endif
+}
+
+int spi_write256(u32 addr) {
+ spiopen();
+ memcpy(_flashram+addr/2,spibigtx+4,256);
+#ifndef WASM
+ if (flashfile) {
+ fseek(flashfile, addr, 0);
+ fwrite(_flashram + addr / 2, 1, 256, flashfile);
+ fflush(flashfile);
+ }
+#endif
+ return 0;
+}
+int spi_read256(u32 addr) {
+ memcpy(spibigrx+4, _flashram + addr / 2, 256);
+ return 0;
+}
+
+
+int spi_readgrain_dma(int gi) {
+ spiopen();
+ spistate = gi;
+ if (spistate == 0)
+ startspi = RDTSC();
+ ++spistate;
+ int start = 0;
+ if (gi) start = grainbufend[gi - 1];
+ int len = grainbufend[gi] - start;
+ u32 addr = grainpos[gi];
+
+ //for (int i = 0; i < len; ++i)
+ // grainbuf[start + i] = ((addr + i - 2) * 256);
+
+ if (len>2)
+ memcpy(((u8*)&grainbuf[start])+4,_flashram+(addr&(MAX_SAMPLE_LEN*8-1)),len*2-4);
+ spi_read_done();
+ return 0;
+}
+#else
+
+volatile bool spidone = false;
+
+void spi_wait(void) {
+ while (!spidone)
+ ;
+ spidone = false;
+}
+
+#define CHECKRV(spirv, msg) if (spirv!=0 ) DebugLog("SPI ERROR %d " msg "\r\n", spirv);
+
+#ifdef NEW_PINOUT
+#define SPI_PORT GPIOE
+#define SPI_CS0_PIN_ GPIO_PIN_1
+#define SPI_CS1_PIN_ GPIO_PIN_0
+#else
+#define SPI_PORT GPIOD
+#define SPI_CS0_PIN_ GPIO_PIN_0
+#define SPI_CS1_PIN_ GPIO_PIN_0
+#endif
+u8 curspipin_=SPI_CS0_PIN_;
+void spi_setchip(u32 addr) {
+ curspipin_ = (addr&(1<<24)) ? SPI_CS1_PIN_ : SPI_CS0_PIN_;
+}
+void spi_setexpanderdac(void) {
+ curspipin_ = 0;
+ hspi2.Instance->CR1 &= ~(1 | 64);
+ hspi2.Instance->CR1 |= 64;
+ SPI_PORT->BSRR = SPI_CS1_PIN_ | SPI_CS0_PIN_;
+ GPIOA->BRR = 1<<8; // dac cs low
+}
+static inline void spi_assert_cs(void) {
+ SPI_PORT->BSRR = SPI_CS1_PIN_ | SPI_CS0_PIN_;
+ hspi2.Instance->CR1 &= ~( 64);
+ hspi2.Instance->CR1 |= 1 | 64;
+
+ SPI_PORT->BRR = curspipin_;
+}
+static inline void spi_release_cs(void) {
+ SPI_PORT->BSRR = SPI_CS1_PIN_ | SPI_CS0_PIN_;
+}
+int spi_writeenable(void) {
+ u8 spitxbuf[1] = { 6 };
+ u8 spirxbuf[1];
+ spi_assert_cs();
+ spidelay();
+ int spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spitxbuf, (uint8_t*) spirxbuf, 1, -1);
+ CHECKRV(spirv,"spi_writeenable");
+ spi_release_cs();
+ spidelay();
+// if (spirv==0) spi_wait();
+ return spirv;
+}
+
+int spi_readid(void) {
+ u8 spitxbuf[6] = { 0x90, 0, 0, 0, 0, 0 };
+ u8 spirxbuf[6] = { 0 };
+ spi_assert_cs();
+ spidelay();
+ int spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spitxbuf, (uint8_t*) spirxbuf, 6, -1);
+ CHECKRV(spirv,"spi_readid");
+ spi_release_cs();
+ spidelay();
+
+// if (spirv==0) spi_wait();
+ return (spirv == 0) ? (spirxbuf[4] + (spirxbuf[5] << 8)) : -1;
+}
+
+int spi_readstatus(void) {
+ u8 spitxbuf[2] = { 5, 0 };
+ u8 spirxbuf[2] = { 0 };
+ spi_assert_cs();
+ spidelay();
+ int spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spitxbuf, (uint8_t*) spirxbuf, 2, -1);
+ CHECKRV(spirv,"spi_readstatus1");
+ spi_release_cs();
+ spidelay();
+ return (spirv == 0) ? (spirxbuf[1]) : -1;
+}
+
+int spi_waitnotbusy(const char *msg, void(*callback)(void)) {
+ int spirv = 0;
+// spi_wait();
+ int i = millis();
+ u8 spitxbuf[1] = { 5 };
+ u8 spirxbuf[1] = { 23 };
+ spi_assert_cs();
+
+ spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spitxbuf, (uint8_t*) spirxbuf, 1, -1);
+ CHECKRV(spirv,"spi_waitnotbusy1");
+ spirxbuf[0] = 0xff;
+ while (spirxbuf[0] & 1) {
+
+ if (callback)
+ callback();
+
+ spirxbuf[0] = 0;
+ spirv=HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spitxbuf, (uint8_t*) spirxbuf, 1, -1);
+ CHECKRV(spirv,"spi_waitnotbusy2");
+// DebugLog("%02x ", spirxbuf[0]);
+ if (spirv) break;
+ }
+ spi_release_cs();
+ spidelay();
+ int t = millis() - i;
+ if (t > 10)
+ DebugLog("flash write/erase operation [%s] took %dms\r\n", msg, t);
+ return spirv;
+}
+int spi_read256(u32 addr);
+
+int spi_erase64k(u32 addr, void (*callback)(void)) {
+ spi_setchip(addr);
+ spi_writeenable();
+ u8 spitxbuf[4] = { 0xd8, addr >> 16, addr >> 8, addr };
+ u8 spirxbuf[4];
+ DebugLog("spi erase %d\r\n", addr);
+ spi_assert_cs();
+ spidelay();
+ int spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spitxbuf, (uint8_t*) spirxbuf, 4, -1);
+ CHECKRV(spirv,"spi_erase1");
+ spi_release_cs();
+ spidelay();
+ if (spirv == 0)
+ spirv = spi_waitnotbusy("erase", callback);
+ else {
+ DebugLog("HAL_SPI_TransmitReceive returned %d in erase\r\n", spirv);
+ }
+ /*
+ memset(spibigrx, 0, sizeof(spibigrx));
+ spi_read256(addr);
+ for (int i = 0; i < 256; ++i) if (spibigrx[i + 4] != (u8)(255)) {
+ DebugLog("erase fail at %d\r\n", addr+i);
+ }
+ */
+ return spirv;
+}
+
+int spi_write256(u32 addr) {
+ spi_setchip(addr);
+ spi_writeenable();
+ spibigtx[0] = 2;
+ spibigtx[1] = addr >> 16;
+ spibigtx[2] = addr >> 8;
+ spibigtx[3] = addr >> 0;
+ spi_assert_cs();
+
+ spidelay();
+ int spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spibigtx, (uint8_t*) spibigrx, 4 + 256, -1);
+ CHECKRV(spirv,"spi_write256");
+
+ spi_release_cs();
+ spidelay();
+
+ if (spirv == 0)
+ spirv = spi_waitnotbusy("write", 0);
+
+ if (0) {
+ spi_read256(addr);
+ if (memcmp(spibigrx+4,spibigtx+4,256)!=0) {
+ DebugLog("spi didnt read what I wrote? %d\r\n", addr);
+ }
+ }
+
+ return spirv;
+}
+
+int spi_read256(u32 addr) {
+ spibigtx[0] = 3;
+ spibigtx[1] = addr >> 16;
+ spibigtx[2] = addr >> 8;
+ spibigtx[3] = addr >> 0;
+ spi_setchip(addr);
+ spi_assert_cs();
+
+ spidelay();
+ int spirv = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) spibigtx, (uint8_t*) spibigrx, 4 + 256, -1);
+ CHECKRV(spirv,"spi_read256");
+ spi_release_cs();
+ spidelay();
+ return spirv;
+}
+
+
+
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) {
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); /* Clear all flags */
+ hdma->Instance->CNDTR = DataLength;
+ if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) {
+ hdma->Instance->CPAR = DstAddress;
+ hdma->Instance->CMAR = SrcAddress;
+ } else {
+ hdma->Instance->CPAR = SrcAddress;
+ hdma->Instance->CMAR = DstAddress;
+ }
+}
+
+void setup_spi_alex_dma(uint32_t txaddr, uint32_t rxaddr, int len) { // len is in 8 bit words
+ // ALEX DMA MODE! fewer interrupts; simpler code.
+ alexdmamode = 1;
+ CLEAR_BIT(hspi2.Instance->CR2, SPI_CR2_LDMATX | SPI_CR2_LDMARX); // Reset the threshold bit
+ SET_BIT(hspi2.Instance->CR2, SPI_RXFIFO_THRESHOLD); // Set RX Fifo threshold according the reception data length: 8bit
+ // config rx dma - transfer complete callback
+ __HAL_DMA_DISABLE(hspi2.hdmarx);
+ DMA_SetConfig(hspi2.hdmarx, (uint32_t) &hspi2.Instance->DR, rxaddr, len);
+ __HAL_DMA_DISABLE_IT(hspi2.hdmarx, (DMA_IT_HT | DMA_IT_TE));
+ __HAL_DMA_ENABLE_IT(hspi2.hdmarx, (DMA_IT_TC));
+ __HAL_DMA_ENABLE(hspi2.hdmarx);
+ SET_BIT(hspi2.Instance->CR2, SPI_CR2_RXDMAEN); // Enable Rx DMA Request
+
+ // config tx dma - no interrupts
+ __HAL_DMA_DISABLE(hspi2.hdmatx);
+ DMA_SetConfig(hspi2.hdmatx, txaddr, (uint32_t) &hspi2.Instance->DR, len);
+ __HAL_DMA_DISABLE_IT(hspi2.hdmatx, (DMA_IT_HT | DMA_IT_TE | DMA_IT_TC));
+ __HAL_DMA_ENABLE(hspi2.hdmatx);
+ if ((hspi2.Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ __HAL_SPI_ENABLE(&hspi2); // Enable SPI peripheral
+ SET_BIT(hspi2.Instance->CR2, SPI_CR2_TXDMAEN);
+}
+
+static u16 daccmd, dacdummy;
+void spi_update_dac(int dacchan) {
+ spistate=MAX_SPI_STATE+dacchan + 1; // the NEXT state
+
+ int data = expander_out[dacchan & 3];
+
+ daccmd = (2<<14) + ((dacchan&3)<<12) + (data & 0xfff);
+ daccmd=(daccmd>>8) | (daccmd<<8);
+ spi_setexpanderdac(); // assert cs for dac
+ setup_spi_alex_dma((uint32_t)&daccmd, (uint32_t)&dacdummy, 2);
+}
+
+
+
+int spi_readgrain_dma(int gi) {
+ spi_release_cs();
+ u32 addr;
+again:
+ addr = grainpos[gi] * 2;
+ spibigtx[0] = 3;
+ spibigtx[1] = addr >> 16;
+ spibigtx[2] = addr >> 8;
+ spibigtx[3] = addr >> 0;
+ spistate = gi;
+ if (spistate==0)
+ startspi = RDTSC();
+ ++spistate;
+ int start = 0;
+ if (gi) start = grainbufend[gi - 1];
+ int len = grainbufend[gi] - start;
+
+ if (len<=2) {
+ if (spistate==MAX_SPI_STATE) {
+ spi_update_dac(0);
+// resetspistate();
+ return 0;
+ }
+ ++gi;
+ goto again;
+ }
+
+
+ if (0) {
+ for (int i=0;i<len;++i)
+
+ grainbuf[start+i]=((addr/2+i-2)*256);
+ if (spistate==MAX_SPI_STATE) {
+ spi_update_dac(0);
+// resetspistate();
+ return 0;
+ }
+ ++gi; goto again;
+ }
+ spi_setchip(addr);
+ spi_assert_cs();
+
+ setup_spi_alex_dma((uint32_t) spibigtx, (uint32_t) (grainbuf+start), len * 2);
+
+ return 0;
+}
+
+
+void alexdmadone(void) {
+ // replacement irq handler for the HAL guff.
+ DMA_HandleTypeDef *hdma = hspi2.hdmarx; /*!< SPI Rx DMA Handle parameters */
+ uint32_t flag_it = hdma->DmaBaseAddress->ISR;
+ uint32_t source_it = hdma->Instance->CCR;
+ if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TC) != 0U)) {
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC | DMA_IT_HT);
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1CU)); /* Clear the transfer complete flag */
+ spi_read_done();
+ }
+}
+
+/*
+ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
+ {
+ spidone=true;
+ }
+ */
+#endif