#include <cstdint>
#include "hardware/5400tp194.h"
#include "spi_test.h"

static volatile int flag_irq_spi;

extern "C"
void spi0IrqHandler() {
	//reset st reg
	unsigned status_spi = SPI0->st;

	//module shutdown
	SPI0->ctrl = 0;
	SPI0->cfg = 0;
	SPI1->ctrl = 0;
	SPI1->cfg = 0;

	flag_irq_spi = 1;
}

void setting_plic_spi() {
	CMM->apb0clken |= CMM_APB0CLKEN_PLIC;

	PLIC->prio[PLIC_CC_SPI0] = 1;
	PLIC->cpu.ie = PLIC_IE_SPI0;
	PLIC->le = PLIC_LE_SPI0;
}

void spi_test() {
	setting_plic_spi();

	//clocking on
	uint32_t clken = CMM_APB0CLKEN_SPI0 | CMM_APB0CLKEN_SPI1;
	CMM->apb0clken |= clken;

	//enabling alternative functions GPIOA
	uint32_t altfen = GPIOA->altf0 | GPIOA_ALTF0_P0_SPI0_MOSI | GPIOA_ALTF0_P1_SPI0_MISO | GPIOA_ALTF0_P2_SPI0_CS
					| GPIOA_ALTF0_P3_SPI0_SCK | GPIOA_ALTF0_P4_SPI1_MOSI | GPIOA_ALTF0_P5_SPI1_MISO
					| GPIOA_ALTF0_P6_SPI1_CS | GPIOA_ALTF0_P7_SPI1_SCK;
	GPIOA->altf0 |= altfen;

	//setting SPI0
	SPI0->cfg = 0x1040025;

	//buffer filling
	for	(uint32_t data = 0xF1; data >= 0xB1; data -= 0x10) {
		SPI0->buf = data;
	}

	//interrupt resolution by NULL_BUF event
	SPI0->msk = 0x10;

	//setting SPI1
	SPI1->cfg = 0x4;

	//buffer filling
	for (uint32_t data = 0; data < 0x7; ++data) {
		SPI1->buf = data;
	}

	//modules activation
	SPI0->ctrl = 0x9;
	SPI1->ctrl = 0x1;

	while(!flag_irq_spi);
	flag_irq_spi = 0;

	//clocking off
	CMM->apb0clken &= ~clken;

	//disabling alternative GPIOA functions
	GPIOA->altf0 &= ~altfen;
}
