/*
 * main.c
 */

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
//#include "inc/hw_gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/udma.h"
#include "driverlib/ssi.h"
#include "driverlib/timer.h"
#include "Peripherals_123.h"
#include "Pinout_123.h"


/*
 * SSI melynas perdavimas baigtas pertraukimo aptarnavimas
 * Jei perdavimas baigtas, palacinu
 */
void ssi_pertraukimas(void)
{
	SSIIntClear(SERIAL_INTERFACE_BLUE, SSI_TXEOT); //numetu pertraukima
	MAP_GPIOPinWrite(LATCH_PORT , LATCH_PIN, LATCH_PIN);//pakeliu latch
	SysCtlDelay(10);
	MAP_GPIOPinWrite(LATCH_PORT , LATCH_PIN, 0);//numetu latch
}


int main(void) {

	uint8_t i, leds_level;
	bool blue_SSI_busy;
	uint32_t step_timer;
    //
    // Enable lazy stacking for interrupt handlers.
    //
    MAP_FPUEnable();
    MAP_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    /*
     * Paleidziu visa periferija, kur pinmux'as sugeneravo
     */
    PortFunctionInit();

    /*
     * Susipildau visus spalvu buferius patestavimui 0/1 paternu
     */
    B_saltinis[0] = 0xAAAACCCC;
    B_saltinis[1] = 0xCCCCAAAA;

    R_saltinis[0] = 0xAAAABBBB;
    R_saltinis[1] = 0xBBBBAAAA;

    G_saltinis[0] = 0xAAAA0001;
    G_saltinis[1] = 0x8000AAAA;

    /*
     * Pakeidziu uDMA
     */
    Init_uDMA_Controller();

    /*
     * prikabinu po DMA kanala visiem SSI
     */
    Config_SSI_uDMA_Transfer_Red();
    Config_SSI_uDMA_Transfer_Green();
    Config_SSI_uDMA_Transfer_Blue();

    /*
     * paleidziu visus SSI dirbti
     */
    Config_SSI_Red();
    Config_SSI_Green();
    Config_SSI_Blue();

    /*
     * Pasakau pertraukimu kontroleriui kad leistu melinam SSI daryti pertraukimus
     */
    //MAP_IntEnable(BLUE_INTERFACE);

    /*
     * Leidziu procesoriaus pertraukimus. Kam man ju reikia? Gal tam, kad periferija galetu
     * pertraukti procesoriu. Tipo kitaip, tik NMI gali pertraukti procesoriu. Visi kiti interuptai
     * sekmingai verda, sukasi, bet iki proco nepapuola, ir procas i juos nereaguoja
     */
    //MAP_IntMasterEnable();

    /*
     * Melyna spalva bus sustumiama paskutine. Reiskia sulaukus pertraukimo is SSI melymos
     * jau visas aukstas uzpildytas ir galima latchint. Leidziu pertraukimus SSI melynai su argumentu
     * SSI_DMATX pertraukimas sauna kai tik DMA perdavimas baigtas, tai pulsas pasirodys vos pradejus duomenis stumti i melyma registra ir iskart baigus. kodel, nezinau
     * SSI_TXEOT pertraukimas sauna tada kai  FIFO buferis tuscias (end of transmition). Taip pat kazkodel sauna pradejus siusti ir baigus siusti
     * SSI_TXFF pertraukimas kai buferis puspilnis ar maziau, sauna pradzioje, o baigus uzdeneruoja
     */
    SSIIntDisable(SERIAL_INTERFACE_BLUE, SSI_RXOR | SSI_RXTO | SSI_RXFF | SSI_TXFF | SSI_DMARX | SSI_DMATX | SSI_TXEOT); //draudziu visus imanomus pertraukimus
    SSIIntClear(SERIAL_INTERFACE_BLUE, SSI_RXOR | SSI_RXTO | SSI_RXFF | SSI_TXFF | SSI_DMARX | SSI_DMATX | SSI_TXEOT); //numetu visas esamas pertraukimo veliavas
    //MAP_SSIIntEnable(SERIAL_INTERFACE_BLUE, SSI_TXEOT); //nustatau pagal kokia veliava pertraukimai turi buti tikrinami
    //SysCtlDelay(10);

    /*
     * Toglinu koja, bus kaip zyme oscilogramoje perdavimo trukmei pradeti matuoti
     */
   // ssi_pertraukimas();
   // SysCtlDelay(1000);

    step_timer = 100; // pries cikla nustatau ISM nulinio bito pasvietimo laika (baze visam ISM)
    /*
     * imituoju 8 ciklus
     */
    for (i = 0; i < 7; i++)
    {
		/*
		 * Startuoju DMA perdavima. Perdavimas trigerina atitinkama SSI transyveri
		 */
		MAP_uDMAChannelRequest(RED_DMA_TX);
		MAP_uDMAChannelRequest(GREEN_DMA_TX);
		MAP_uDMAChannelRequest(BLUE_DMA_TX);
	
		blue_SSI_busy = 1; //sakau kad SSI dirba
	
		   /*
		    * amzinas ciklas tusciai suku proca kol melynas SSI atsilaisvims
		    */
			while(blue_SSI_busy)
			{
				blue_SSI_busy = MAP_SSIBusy(SERIAL_INTERFACE_BLUE); // vis klausiu ar jau atsilaisvino
			}
		/*
		 * patoglinu latch koja
		 */
		ssi_pertraukimas();
	
		/*
		 * Impulso Svorio Moduliatorius
		 * Po to kai nuliniai visu ledu bitai buvo nusiusti i regstra, ledai uzsvieciami tam tikra laika
		 * tas tam tikras laikas ilginamas dvigubai, su kiekvienu vyresniu ledu bits siunciamu i registra
		 * Taip 8 kartus ir gaunasi tikra 24bitu spalva
		 * Taip atidirbamas 1 aukstas
		 */
	
		step_timer <<= 1; //tiesiog pasiftinu per skilti ir padvigubinu laika
		SysCtlDelay(step_timer);
		
		/*
		 * uztaisau per nauja DMA agregata
		 */
		MAP_uDMAChannelTransferSet(UDMA_CH13_SSI2TX | UDMA_PRI_SELECT,
								   UDMA_MODE_BASIC,
								   &R_saltinis[0],
								   (void *) (SSI2_BASE + SSI_O_DR),
								   4);//per nauja uztaisau raudona siuntima
		MAP_uDMAChannelEnable(UDMA_CH13_SSI2TX); // ir paleidziu kanala dirbti
	
		MAP_uDMAChannelTransferSet(UDMA_CH12_SSI2RX | UDMA_PRI_SELECT,
								   UDMA_MODE_BASIC,
								   (void *) (SSI2_BASE + SSI_O_DR),
								   &R_klaidos,
								   4);//per nauja uztaisau raudona gavima
		MAP_uDMAChannelEnable(UDMA_CH12_SSI2RX); // ir paleidziu kanala dirbti
	
		MAP_uDMAChannelTransferSet(UDMA_CH15_SSI3TX | UDMA_PRI_SELECT,
								   UDMA_MODE_BASIC,
								   &G_saltinis[0],
								   (void *) (SSI3_BASE + SSI_O_DR),
								   4);//per nauja uztaisau zalia siuntima
		MAP_uDMAChannelEnable(UDMA_CH15_SSI3TX); // ir paleidziu kanala dirbti
	
		MAP_uDMAChannelTransferSet(UDMA_CH14_SSI3RX | UDMA_PRI_SELECT,
								   UDMA_MODE_BASIC,
								   (void *) (SSI3_BASE + SSI_O_DR),
								   &G_klaidos,
								   4);//per nauja uztaisau zalia gavima
		MAP_uDMAChannelEnable(UDMA_CH14_SSI3RX); // ir paleidziu kanala dirbti
	
		MAP_uDMAChannelTransferSet(UDMA_CH11_SSI0TX | UDMA_PRI_SELECT,
								   UDMA_MODE_BASIC,
								   &B_saltinis[0],
								   (void *) (SSI0_BASE + SSI_O_DR),
								   4); //per nauja uztaisau melyna siuntima
		MAP_uDMAChannelEnable(UDMA_CH11_SSI0TX); // ir paleidziu kanala dirbti
	
		MAP_uDMAChannelTransferSet(UDMA_CH10_SSI0RX | UDMA_PRI_SELECT,
							   UDMA_MODE_BASIC,
							   (void *) (SSI0_BASE + SSI_O_DR),
							   &B_klaidos,
							   4);//per nauja uztaisau melyna gavima
		MAP_uDMAChannelEnable(UDMA_CH10_SSI0RX); // ir paleidziu kanala dirbti

    }
    /*
     * paskutinis pasiftinimas, pasviecia vyriausia baita, jis jau uz ciklo ribu
     * tik dabar jau nebelacinu, o blankinu (nors nebutina, ir pereinu i sekanti auksta
     */
	step_timer <<= 1; //tiesiog pasiftinu per skilti ir padvigubinu laika
	
	SysCtlDelay(step_timer);
	
	leds_level++; //cia bus funkcija kuri pagesins einama leveli ir uzdegs sekanti
	
	ssi_pertraukimas(); //tieiog uzsidedu zyme ant oscilogramos kada paskutinis pasvietimas baigtas

    /*
     * Amzinas ciklas, kur procikas praleidzia visa laika, nes viskas veikia automatu, per DMA ar interruptus
     */
    while(1)
    {

    }
	
	//return 0;