From a78f1ea12947fc26aaa9f8d45664b5240d98205c Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Mon, 20 Jun 2022 11:40:55 -0400 Subject: [PATCH] Implement the SPI protocol and a tester --- base/base.h | 4 ++++ flake.nix | 30 +++++++++++++++++++++++++++++- spi/spi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ spi/spi.h | 18 ++++++++++++++++++ spi_test/main.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 spi/spi.c create mode 100644 spi/spi.h create mode 100644 spi_test/main.c diff --git a/base/base.h b/base/base.h index 86fdeb0..12e73e3 100644 --- a/base/base.h +++ b/base/base.h @@ -35,6 +35,10 @@ inline void clear_pin(io_pin_t *pin) { *(pin->port) &= ~(_BV(pin->addr)); } +inline int read_pin(io_pin_t *pin) { + return (*(pin->port) & _BV(pin->addr)) > 0; +} + typedef struct RNG { uint8_t mod; int8_t a; diff --git a/flake.nix b/flake.nix index e756f68..5d3f716 100644 --- a/flake.nix +++ b/flake.nix @@ -49,7 +49,7 @@ includes = [ "base" "morse" ]; MCU = "atmega32u4"; - CHIP_SELECT = "AVR_ATmego32u4"; + CHIP_SELECT = "AVR_ATmega32u4"; F_CPU = "8000000"; CFLAGS = ''-O -finline-functions -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -DF_CPU=${F_CPU} -std=gnu99 -D__${CHIP_SELECT}__=1 -mmcu=${MCU} -DAVR=1''; INCLUDE_DIRS = lib.concatStringsSep " " (map (dir: "-I${src}/${dir}") includes); @@ -66,6 +66,34 @@ ''; }; + packages."x86_64-linux"."spi_test" = + let + pkgs = import nixpkgs { system = "x86_64-linux"; }; + lib = pkgs.lib; + avr = pkgs.pkgsCross.avr.buildPackages; + in pkgs.stdenv.mkDerivation rec { + name = "morse-tx"; + src = ./.; + + includes = [ "base" "spi" ]; + + MCU = "atmega32u4"; + CHIP_SELECT = "AVR_ATmega32u4"; + F_CPU = "8000000"; + CFLAGS = ''-O -finline-functions -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -DF_CPU=${F_CPU} -std=gnu99 -D__${CHIP_SELECT}__=1 -mmcu=${MCU} -DAVR=1''; + INCLUDE_DIRS = lib.concatStringsSep " " (map (dir: "-I${src}/${dir}") includes); + + buildPhase = '' + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o spi.o -c ${src}/spi/spi.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o main.o -c ${src}/spi_test/main.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} -o main.elf main.o spi.o + $OBJCOPY -O ihex main.elf main.hex + ''; + installPhase = '' + mkdir $out + cp main.elf main.hex $out + ''; + }; devShell."x86_64-linux" = let diff --git a/spi/spi.c b/spi/spi.c new file mode 100644 index 0000000..ca4d95d --- /dev/null +++ b/spi/spi.c @@ -0,0 +1,42 @@ + +#include +#include + +void initialize_spi(spi_t *spi) { + set_pin_direction(&spi->clock, PIN_OUT); + set_pin_direction(&spi->data_out, PIN_OUT); + set_pin_direction(&spi->data_in, PIN_IN); + set_pin_direction(&spi->chip_select, PIN_OUT); +} + +uint8_t transfer_byte(spi_t *spi, uint8_t output) { + uint8_t input = 0; + int input_bit; + + set_pin(&spi->chip_select); + + for (int i = 7; i >= 0; i--) { + clear_pin(&spi->clock); + if (output & _BV(i)) { + set_pin(&spi->data_out); + } else { + clear_pin(&spi->data_out); + } + _delay_us(10); + set_pin(&spi->clock); + _delay_us(10); + //input_bit = read_pin(&spi->data_in); + //input <<= input_bit; + } + clear_pin(&spi->clock); + _delay_us(10); + clear_pin(&spi->chip_select); + return input; +} + +/* +void send_bytes(spi_t *line, u8 *byte, size_t length, u8 *input, size_t input_length) { + +} +*/ + diff --git a/spi/spi.h b/spi/spi.h new file mode 100644 index 0000000..6a090eb --- /dev/null +++ b/spi/spi.h @@ -0,0 +1,18 @@ + +#ifndef __MORSE_H__ +#define __MORSE_H__ + +#include +#include + +typedef struct SPI { + io_pin_t clock; + io_pin_t data_out; + io_pin_t data_in; + io_pin_t chip_select; +} spi_t; + +void initialize_spi(spi_t *spi); +uint8_t transfer_byte(spi_t *spi, uint8_t output); + +#endif diff --git a/spi_test/main.c b/spi_test/main.c new file mode 100644 index 0000000..4d203e6 --- /dev/null +++ b/spi_test/main.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +int main(void) { + spi_t spi = (spi_t){ + .clock = { .ddr = &DDRF, .port = &PORTF, .addr = 7 }, + .data_out = { .ddr = &DDRF, .port = &PORTF, .addr = 6 }, + .data_in = { .ddr = &DDRF, .port = &PORTF, .addr = 5 }, + .chip_select = { .ddr = &DDRF, .port = &PORTF, .addr = 4 }, + }; + + io_pin_t light = { .ddr = &DDRC, .port = &PORTC, .addr = 7 }; + + initialize_spi(&spi); + + while (1) { + set_pin(&light); + transfer_byte(&spi, 0xaa); + _delay_ms(1000); + clear_pin(&light); + _delay_ms(1000); + } + + /* + while(1) { + set_pin(&spi.clock); + set_pin(&spi.data_out); + _delay_ms(500); + clear_pin(&spi.clock); + clear_pin(&spi.data_out); + _delay_ms(500); + } + */ +}