From 1c9a329d7beb9320ea1bb91b6d87bfefb897dfe8 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Fri, 17 Jun 2022 23:06:10 -0400 Subject: [PATCH] Improve the base pin, set up morse code flasher on feather 32u4 --- base/base.h | 25 ++++++++++++-- flake.nix | 30 +++++++++++++++++ flash-feather | 1 + morse/morse.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ morse/morse.h | 19 +++++++++++ morse_tx/main.c | 15 +++++++++ 6 files changed, 177 insertions(+), 3 deletions(-) create mode 100755 flash-feather create mode 100644 morse/morse.c create mode 100644 morse/morse.h create mode 100644 morse_tx/main.c diff --git a/base/base.h b/base/base.h index c44c208..86fdeb0 100644 --- a/base/base.h +++ b/base/base.h @@ -3,17 +3,36 @@ #ifndef __BASE_H__ #define __BASE_H__ +#define PIN_OUT 1 +#define PIN_IN 0 + typedef struct IO_PIN { + volatile uint8_t *ddr; volatile uint8_t *port; - uint8_t pin; + uint8_t addr; } io_pin_t; +/* +#define GPIOA(addr) (io_pin_t){ .ddr = &DDRA, .port = &PORTA, .addr = addr } +#define GPIOB(addr) (io_pin_t){ .ddr = &DDRB, .port = &PORTB, .addr = addr } +#define GPIOC(addr) (io_pin_t){ .ddr = &DDRC, .port = &PORTC, .addr = addr } +#define GPIOD(addr) (io_pin_t){ .ddr = &DDRD, .port = &PORTD, .addr = addr } +*/ + +inline void set_pin_direction(io_pin_t *pin, int direction) { + if (direction == PIN_OUT) { + *(pin->ddr) |= _BV(pin->addr); + } else { + *(pin->ddr) &= ~(_BV(pin->addr)); + } +} + inline void set_pin(io_pin_t *pin) { - *(pin->port) |= 1 << pin->pin; + *(pin->port) |= _BV(pin->addr); } inline void clear_pin(io_pin_t *pin) { - *(pin->port) &= 0xff ^ (1 << pin->pin); + *(pin->port) &= ~(_BV(pin->addr)); } typedef struct RNG { diff --git a/flake.nix b/flake.nix index f5f6c1f..e756f68 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,36 @@ ''; }; + packages."x86_64-linux"."morse-tx" = + 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" "morse" ]; + + MCU = "atmega32u4"; + CHIP_SELECT = "AVR_ATmego32u4"; + 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 morse.o -c ${src}/morse/morse.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} ${INCLUDE_DIRS} -o main.o -c ${src}/morse_tx/main.c + ${avr.gcc}/bin/avr-gcc ${CFLAGS} -o main.elf main.o morse.o + $OBJCOPY -O ihex main.elf main.hex + ''; + installPhase = '' + mkdir $out + cp main.elf main.hex $out + ''; + }; + + devShell."x86_64-linux" = let pkgs = import nixpkgs { system = "x86_64-linux"; }; diff --git a/flash-feather b/flash-feather new file mode 100755 index 0000000..9f7c2fe --- /dev/null +++ b/flash-feather @@ -0,0 +1 @@ +avrdude -c avr109 -P /dev/ttyACM0 -p m32u4 -D -U flash:w:$1:i diff --git a/morse/morse.c b/morse/morse.c new file mode 100644 index 0000000..a63cace --- /dev/null +++ b/morse/morse.c @@ -0,0 +1,90 @@ +#include +#include +#include "morse.h" + +/* TODO: all of this is a candidate for living in an EEPROM */ +typedef struct morse_codepoint { + size_t length; + uint8_t values[5]; +} morse_codepoint_t; + +const struct morse_codepoint MORSE[] = { + /* 0 */ { .length = 5, .values = { DASH, DASH, DASH, DASH, DASH } }, + /* 1 */ { .length = 5, .values = { DOT, DASH, DASH, DASH, DASH } }, + /* 2 */ { .length = 5, .values = { DOT, DOT, DASH, DASH, DASH } }, + /* 3 */ { .length = 5, .values = { DOT, DOT, DOT, DASH, DASH } }, + /* 4 */ { .length = 5, .values = { DOT, DOT, DOT, DOT, DASH } }, + /* 5 */ { .length = 5, .values = { DOT, DOT, DOT, DOT, DOT } }, + /* 6 */ { .length = 5, .values = { DASH, DOT, DOT, DOT, DOT } }, + /* 7 */ { .length = 5, .values = { DASH, DASH, DOT, DOT, DOT } }, + /* 8 */ { .length = 5, .values = { DASH, DASH, DASH, DOT, DOT } }, + /* 9 */ { .length = 5, .values = { DASH, DASH, DASH, DASH, DOT } }, + /* a */ { .length = 2, .values = { DOT, DASH } }, + /* b */ { .length = 4, .values = { DASH, DOT, DOT, DOT } }, + /* c */ { .length = 4, .values = { DASH, DOT, DASH, DOT } }, + /* d */ { .length = 3, .values = { DASH, DOT, DOT } }, + /* e */ { .length = 1, .values = { DOT } }, + /* f */ { .length = 4, .values = { DOT, DOT, DASH, DOT } }, + /* g */ { .length = 3, .values = { DASH, DASH, DOT } }, + /* h */ { .length = 4, .values = { DOT, DOT, DOT, DOT } }, + /* i */ { .length = 2, .values = { DOT, DOT } }, + /* j */ { .length = 4, .values = { DOT, DASH, DASH, DASH } }, + /* k */ { .length = 3, .values = { DASH, DOT, DASH } }, + /* l */ { .length = 4, .values = { DOT, DASH, DOT, DOT } }, + /* m */ { .length = 2, .values = { DASH, DASH } }, + /* n */ { .length = 2, .values = { DASH, DOT } }, + /* o */ { .length = 3, .values = { DASH, DASH, DASH } }, + /* p */ { .length = 4, .values = { DOT, DASH, DASH, DOT } }, + /* q */ { .length = 4, .values = { DASH, DASH, DOT, DASH } }, + /* r */ { .length = 3, .values = { DOT, DASH, DOT } }, + /* s */ { .length = 3, .values = { DOT, DOT, DOT } }, + /* t */ { .length = 1, .values = { DASH } }, + /* u */ { .length = 3, .values = { DOT, DOT, DASH } }, + /* v */ { .length = 4, .values = { DOT, DOT, DOT, DASH } }, + /* w */ { .length = 3, .values = { DOT, DASH, DASH } }, + /* x */ { .length = 4, .values = { DASH, DOT, DOT, DASH } }, + /* y */ { .length = 4, .values = { DASH, DOT, DASH, DASH } }, + /* z */ { .length = 4, .values = { DASH, DASH, DOT, DOT } }, +}; + +const struct morse_codepoint * morse_lookup(char val) { + size_t idx = -1; + if (val >= '0' && val <= '9') { + idx = val - '0'; + } else if (val >= 'a' && val <= 'z') { + idx = (val - 'a') + 10; + } else if (val >= 'A' && val <= 'Z') { + idx = (val - 'A') + 10; + } + if (idx < 0) return NULL; + return &MORSE[idx]; +} + +void send_codepoint(io_pin_t *gpio, const struct morse_codepoint *codepoint) { + const uint8_t one = 1 << gpio->addr; + for (size_t i = 0; i < codepoint->length; i++) { + *gpio->port = *(gpio->port) | one; + if (codepoint->values[i] == DOT) { + _delay_ms(DOT * SCALE); + } else { + _delay_ms(DASH * SCALE); + } + *gpio->port = *(gpio->port) & ~one; + _delay_ms(DIVIDER * SCALE); + } + _delay_ms(INTERCHAR * SCALE); +} + +void send_morse(io_pin_t *gpio, char *message) { + for (size_t i = 0; i < strlen(message); i++) { + if (message[i] == ' ') { + _delay_ms(INTERWORD * SCALE); + } + const struct morse_codepoint *codepoint = morse_lookup(message[i]); + if (codepoint != NULL) { + send_codepoint(gpio, codepoint); + } + } +} + + diff --git a/morse/morse.h b/morse/morse.h new file mode 100644 index 0000000..4b7e0c6 --- /dev/null +++ b/morse/morse.h @@ -0,0 +1,19 @@ + +#ifndef __MORSE_H__ +#define __MORSE_H__ + +#include +#include +#include + +/* TODO: make this parameterizable */ +#define DOT 1 +#define DASH 3 +#define DIVIDER 1 +#define INTERCHAR 3 +#define INTERWORD 4 +#define SCALE 100 + +void send_morse(io_pin_t *gpio, char *message); + +#endif diff --git a/morse_tx/main.c b/morse_tx/main.c new file mode 100644 index 0000000..bbb7bd1 --- /dev/null +++ b/morse_tx/main.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +int main(void) { + // io_pin_t gpio = (io_pin_t){ .ddr = &DDRB, .port = &PORTB, .addr = 7 }; + io_pin_t gpio = (io_pin_t){ .ddr = &DDRB, .port = &PORTB, .addr = 7 }; + set_pin_direction(&gpio, PIN_OUT); + while(1) { + send_morse(&gpio, "saluton mondo"); + _delay_ms(2000); + } + return 0; +}