/*
 * Copyright(C) Paul und Scherer (mct.de/mct.net)
 *
 * This example demonstrates how to...
 *
 *  ... use the SPI.
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <target.h>

/*
 * The SPI is setup as master.
 *
 * The SPI rate is pclk/SPCCR. The value for SPCCR must be
 * an even number >7. For your application modify settings
 * like phase, polarity etc. accordingly!
 *
 * Note: A pullup is needed for slave select (=P0.7), when
 * in master mode!
 */
static void
spi_init(void)
{
	Intern_pinsel0 |= 0x5500;		// enable SPI pins
	Intern_spcr     = 0x20;			// set master mode
	Intern_spccr    = 8;			// SCK =pclk/8
}

/*
 * SPI transfer
 *
 * Return received data. On error,
 * errno is set to the SPI status.
 */
static int
spi_xfer(int c)
{
	int stat;				// SPI status

	Intern_spdr = c;			// start transfer

	/*
	 * Wait for transfer complete or error
	 * (mask the reserved bits 0, 1 and 2).
	 */
	while (!(stat = Intern_spsr&0xf8)) ;

	if (stat != 0x80) errno = stat;
	return Intern_spdr;
}

/*
 * Test the SPI in loopback mode, i.e.
 *
 *  MISO (=P0.5) connected to
 *  MOSI (=P0.6).
 *
 * The program exits on any SPI error.
 *
 * Note: Applications with "real" SPI devices
 * need to select exactly ONE device prior to
 * starting transfers.
 */
int
main(void)
{
	/*
	 * Here:
	 * De-select all SPI devices!
	 */

	spi_init();				// initialize SPI
	while (1) {
		int sc, rc;			// send/receive char

		puts("Hit any key...");
		sc = getchar();

		/*
		 * Here:
		 * De-select all SPI devices!
		 * Select desired SPI device!
		 */

		printf("\nTransferring 0x%02x... ", sc);
		if (errno = 0, rc = spi_xfer(sc), errno) break;
		printf("received 0x%02x\n", rc);
		if (rc != sc) puts("Loopback FAILED!\7");
	}
	putchar('\n');
	if (errno&0x08) puts("--ERROR: Slave abort");
	if (errno&0x10) puts("--ERROR: Mode fault");
	if (errno&0x20) puts("--ERROR: Read overrun");
	if (errno&0x40) puts("--ERROR: Write collision");

	abort();
}
