2 * Copyright © 2011 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 __xdata struct ao_fifo ao_spi_slave_rx_fifo;
21 __xdata struct ao_fifo ao_spi_slave_tx_fifo;
23 static volatile uint8_t ao_spi_slave_tx_started;
26 ao_spi_slave_tx_start(void)
28 if (!ao_spi_slave_tx_started && !ao_fifo_empty(ao_spi_slave_tx_fifo)) {
29 ao_spi_slave_tx_started = 1;
30 ao_fifo_remove(ao_spi_slave_tx_fifo, SPDR);
39 if (SPIF & (1 << SPIF)) {
41 if (!ao_fifo_full(ao_spi_slave_rx_fifo))
42 ao_fifo_insert(ao_spi_slave_rx_fifo, byte);
43 ao_spi_slave_tx_started = 0;
44 ao_spi_slave_tx_start();
45 ao_wakeup(&ao_spi_slave_rx_fifo);
46 ao_wakeup(&ao_spi_slave_tx_fifo);
51 ao_spi_slave_put(uint8_t b) __critical
54 while (ao_fifo_full(ao_spi_slave_tx_fifo))
55 ao_sleep(&ao_spi_slave_tx_fifo);
56 ao_fifo_insert(ao_spi_slave_tx_fifo, b);
57 ao_spi_slave_tx_start();
62 ao_spi_slave_get(void) __critical
67 while (ao_fifo_empty(ao_spi_slave_rx_fifo))
68 ao_sleep(&ao_spi_slave_rx_fifo);
69 ao_fifo_remove(ao_spi_slave_rx_fifo, b);
75 ao_spi_slave_read(uint8_t *data, int len)
79 *data++ = ao_spi_slave_get();
84 ao_spi_slave_write(uint8_t *data, int len)
87 ao_spi_slave_put(*data++);
88 (void) ao_spi_slave_get();
93 ao_spi_slave_init(void)
95 SPCR = (1 << SPIE) | /* Enable SPI interrupts */
96 (1 << SPE) | /* Enable SPI */
97 (0 << DORD) | /* MSB first */
98 (0 << MSTR) | /* Slave mode */
99 (0 << CPOL) | /* Clock low when idle */
100 (0 << CPHA); /* Sample at leading clock edge */