Implement the SPI protocol and a tester

i2c
Savanni D'Gerinel 2022-06-20 11:40:55 -04:00
parent 1c9a329d7b
commit a78f1ea129
5 changed files with 129 additions and 1 deletions

View File

@ -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;

View File

@ -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

42
spi/spi.c Normal file
View File

@ -0,0 +1,42 @@
#include <spi.h>
#include <util/delay.h>
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) {
}
*/

18
spi/spi.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef __MORSE_H__
#define __MORSE_H__
#include <base.h>
#include <stdlib.h>
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

36
spi_test/main.c Normal file
View File

@ -0,0 +1,36 @@
#include <avr/io.h>
#include <util/delay.h>
#include <base.h>
#include <spi.h>
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);
}
*/
}