/* 
 * "Small Hello World" example. 
 * 
 * This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
 * the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example 
 * designs. It requires a STDOUT  device in your system's hardware. 
 *
 * The purpose of this example is to demonstrate the smallest possible Hello 
 * World application, using the Nios II HAL library.  The memory footprint
 * of this hosted application is ~332 bytes by default using the standard 
 * reference design.  For a more fully featured Hello World application
 * example, see the example titled "Hello World".
 *
 * The memory footprint of this example has been reduced by making the
 * following changes to the normal "Hello World" example.
 * Check in the Nios II Software Developers Manual for a more complete 
 * description.
 * 
 * In the SW Application project (small_hello_world):
 *
 *  - In the C/C++ Build page
 * 
 *    - Set the Optimization Level to -Os
 * 
 * In System Library project (small_hello_world_syslib):
 *  - In the C/C++ Build page
 * 
 *    - Set the Optimization Level to -Os
 * 
 *    - Define the preprocessor option ALT_NO_INSTRUCTION_EMULATION 
 *      This removes software exception handling, which means that you cannot 
 *      run code compiled for Nios II cpu with a hardware multiplier on a core 
 *      without a the multiply unit. Check the Nios II Software Developers 
 *      Manual for more details.
 *
 *  - In the System Library page:
 *    - Set Periodic system timer and Timestamp timer to none
 *      This prevents the automatic inclusion of the timer driver.
 *
 *    - Set Max file descriptors to 4
 *      This reduces the size of the file handle pool.
 *
 *    - Check Main function does not exit
 *    - Uncheck Clean exit (flush buffers)
 *      This removes the unneeded call to exit when main returns, since it
 *      won't.
 *
 *    - Check Don't use C++
 *      This builds without the C++ support code.
 *
 *    - Check Small C library
 *      This uses a reduced functionality C library, which lacks  
 *      support for buffering, file IO, floating point and getch(), etc. 
 *      Check the Nios II Software Developers Manual for a complete list.
 *
 *    - Check Reduced device drivers
 *      This uses reduced functionality drivers if they're available. For the
 *      standard design this means you get polled UART and JTAG UART drivers,
 *      no support for the LCD driver and you lose the ability to program 
 *      CFI compliant flash devices.
 *
 *    - Check Access device drivers directly
 *      This bypasses the device file system to access device drivers directly.
 *      This eliminates the space required for the device file system services.
 *      It also provides a HAL version of libc services that access the drivers
 *      directly, further reducing space. Only a limited number of libc
 *      functions are available in this configuration.
 *
 *    - Use ALT versions of stdio routines:
 *
 *           Function                  Description
 *        ===============  =====================================
 *        alt_printf       Only supports %s, %x, and %c ( < 1 Kbyte)
 *        alt_putstr       Smaller overhead than puts with direct drivers
 *                         Note this function doesn't add a newline.
 *        alt_putchar      Smaller overhead than putchar with direct drivers
 *        alt_getchar      Smaller overhead than getchar with direct drivers
 *
 */

#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/HAL/inc/alt_types.h"
#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/HAL/inc/sys/alt_stdio.h"
#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/HAL/inc/io.h"
#include "system.h"
#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/HAL/inc/sys/alt_cache.h"
#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/drivers/inc/altera_avalon_spi.h"
#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/drivers/inc/altera_avalon_spi_regs.h"
#include "C:/intelFPGA_lite/nios_spiv1/software/nios_spiv1_bsp/HAL/inc/sys/alt_irq.h"


//This is the ISR that runs when the SPI Slave receives data
static void spi_rx_isr(void* isr_context){
alt_printf("ISR :) %x \n" , IORD_ALTERA_AVALON_SPI_RXDATA(SPI_0_BASE));

//This resets the IRQ flag. Otherwise the IRQ will continuously run.
IOWR_ALTERA_AVALON_SPI_STATUS(SPI_0_BASE, 0x0);
}

int main()
{
alt_printf("Hello from Nios II!\n");
int return_code,ret;
char spi_command_string_tx[10] = "$HELLOABC*";
char spi_command_string_rx[10] = "$HELLOABC*";

//This registers the Slave IRQ with NIOS
ret = alt_ic_isr_register(SPI_0_IRQ_INTERRUPT_CONTROLLER_ID,SPI_0_IRQ,spi_rx_isr,(void *)spi_command_string_tx,0x0);
alt_printf("IRQ register return %x \n", ret);

//You need to enable the IRQ in the IP core control register as well.
IOWR_ALTERA_AVALON_SPI_CONTROL(SPI_0_BASE,ALTERA_AVALON_SPI_CONTROL_SSO_MSK | ALTERA_AVALON_SPI_CONTROL_IRRDY_MSK);

//Just calling the ISR to see if the function is OK.
spi_rx_isr(NULL);
return_code = alt_avalon_spi_command(SPI_0_BASE,0 , 1, spi_command_string_tx, 0, spi_command_string_rx, 0);
return_code = alt_avalon_spi_command(SPI_0_BASE,0 , 1, &spi_command_string_tx[1], 0, spi_command_string_rx, 0);
return_code = alt_avalon_spi_command(SPI_0_BASE,0 , 1, &spi_command_string_tx[2], 0, spi_command_string_rx, 0);
return_code = alt_avalon_spi_command(SPI_0_BASE,0 , 1, &spi_command_string_tx[3], 0, spi_command_string_rx, 0);

if(return_code < 0)
alt_printf("ERROR SPI TX RET = %x \n" , return_code);
alt_printf("Transmit done. RET = %x spi_rx %x\n",return_code,spi_command_string_rx[0]);

//RX is done via interrupts.
alt_printf("Rx done \n");
return 0;
}
