From bf92ffb5bff9eedb36df697397b9a6ae27bc168e Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 20 Nov 2018 11:39:42 -0500 Subject: avr: Split gpio.c into gpio.c, adc.c, hard_pwm.c, and spi.c Split up gpio.c into multiple files in an effort to make the code a little more understandable. Signed-off-by: Kevin O'Connor --- src/avr/spi.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/avr/spi.c (limited to 'src/avr/spi.c') diff --git a/src/avr/spi.c b/src/avr/spi.c new file mode 100644 index 00000000..bf0738c1 --- /dev/null +++ b/src/avr/spi.c @@ -0,0 +1,120 @@ +// Serial Peripheral Interface (SPI) support +// +// Copyright (C) 2016-2018 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "autoconf.h" // CONFIG_MACH_atmega644p +#include "command.h" // shutdown +#include "gpio.h" // spi_setup +#include "internal.h" // GPIO +#include "pgm.h" // READP +#include "sched.h" // sched_shutdown + +#if CONFIG_MACH_atmega168 || CONFIG_MACH_atmega328 || CONFIG_MACH_atmega328p +static const uint8_t SS = GPIO('B', 2), SCK = GPIO('B', 5); +static const uint8_t MOSI = GPIO('B', 3), MISO = GPIO('B', 4); +#elif CONFIG_MACH_atmega644p || CONFIG_MACH_atmega1284p +static const uint8_t SS = GPIO('B', 4), SCK = GPIO('B', 7); +static const uint8_t MOSI = GPIO('B', 5), MISO = GPIO('B', 6); +#elif CONFIG_MACH_at90usb1286 || CONFIG_MACH_at90usb646 || CONFIG_MACH_atmega32u4 || CONFIG_MACH_atmega1280 || CONFIG_MACH_atmega2560 +static const uint8_t SS = GPIO('B', 0), SCK = GPIO('B', 1); +static const uint8_t MOSI = GPIO('B', 2), MISO = GPIO('B', 3); +#endif + +static void +spi_init(void) +{ + if (!(GPIO2REGS(SS)->mode & GPIO2BIT(SS))) + // The SS pin must be an output pin (but is otherwise unused) + gpio_out_setup(SS, 0); + gpio_out_setup(SCK, 0); + gpio_out_setup(MOSI, 0); + gpio_in_setup(MISO, 0); + + SPCR = (1< 3) + shutdown("Invalid spi_setup parameters"); + + // Make sure the SPI interface is enabled + spi_init(); + + // Setup rate + struct spi_config config = {0, 0}; + if (rate >= (CONFIG_CLOCK_FREQ / 2)) { + config.spsr = (1<= (CONFIG_CLOCK_FREQ / 4)) { + config.spcr = 0; + } else if (rate >= (CONFIG_CLOCK_FREQ / 8)) { + config.spcr = 1; + config.spsr = (1<= (CONFIG_CLOCK_FREQ / 16)) { + config.spcr = 1; + } else if (rate >= (CONFIG_CLOCK_FREQ / 32)) { + config.spcr = 2; + config.spsr = (1<= (CONFIG_CLOCK_FREQ / 64)) { + config.spcr = 2; + } else { + config.spcr = 3; + } + + // Setup mode + config.spcr |= (1<