sd-card: Only add header to the results file if it’s empty
[brewing-logger:firmware.git] / spi.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Brewing Logger.
4  * Copyright (C) Philip Withnall 2012 <philip@tecnocode.co.uk>
5  *
6  * Brewing Logger is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Brewing Logger is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Brewing Logger.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* References: ATmega644A manual, Section 18. */
21
22 #include <avr/io.h>
23
24 #include "config.h"
25 #include "spi.h"
26
27 /**
28  * \file
29  * \brief SPI bus control.
30  *
31  * Utility functions to initialise and control the SPI bus. This includes enabling and disabling chip selects on different bus slaves, as well as
32  * transmitting bytes from the master (the microcontroller) to the slaves.
33  *
34  * The system uses a single shared SPI bus, which the microcontroller is always the master of. Chip selection is done using standard GPIO ports on the
35  * microcontroller.
36  */
37
38 /**
39  * \brief Initialise SPI bus.
40  *
41  * Initialise the SPI bus with the microcontroller as the bus master. Set the chip selects of all slaves to initially be deselected.
42  */
43 void spi_init (void)
44 {
45         /* Set the data direction of the SPI port. MOSI, SCK, nSS and the CSs are outputs, everything else is an input. */
46         SPI_DDR = (1 << DD_MOSI) | (1 << DD_SCK) | (1 << DD_nSS) | (1 << SPI_CS_SD_CARD) | (1 << SPI_CS_FLASH);
47
48         /* Enable SPI, MSB first, master mode, CPOL 0 (SCK low on idle), CPHA 0 (leading sample/trailing setup), set clock rate fck/4 = 250kHz */
49         SPCR = (1 << SPE) | (1 << MSTR);
50
51         /* Set the chip selects to 1 (deselected). (Note that the chip selects are inverted. */
52         SPI_PORT |= (1 << SPI_CS_SD_CARD) | (1 << SPI_CS_FLASH);
53 }
54
55 void spi_select (uint8_t chip_select)
56 {
57         /* Select one of the chips and disable the other. */
58         if (chip_select == SPI_CS_SD_CARD) {
59                 SPI_PORT |= (1 << SPI_CS_FLASH);
60                 SPI_PORT &= ~(1 << SPI_CS_SD_CARD);
61         } else {
62                 SPI_PORT |= (1 << SPI_CS_SD_CARD);
63                 SPI_PORT &= ~(1 << SPI_CS_FLASH);
64         }
65 }
66
67 void spi_deselect (void)
68 {
69         /* Deselect all chips. */
70         SPI_PORT |= (1 << SPI_CS_SD_CARD) | (1 << SPI_CS_FLASH);
71 }
72
73 void spi_enable (void)
74 {
75         /* Power up and re-initialise SPI. */
76         PRR0 &= ~(1 << PRSPI);
77         spi_init ();
78 }
79
80 void spi_disable (void)
81 {
82         /* Disable SPI. */
83         SPCR &= ~(1 << SPE);
84
85         /* Power it down. */
86         PRR0 |= (1 << PRSPI);
87 }
88
89 uint8_t spi_transmit_byte (uint8_t data)
90 {
91         /* Push the data into the transmit buffer. */
92         SPDR = data;
93
94         /* Poll until transmission completes. */
95         while (!(SPSR & (1 << SPIF)));
96
97         /* Read the response byte. */
98         return SPDR;
99 }