From 6adfd7b8ecfee0cfefc74c690cecaf0e05ce25e0 Mon Sep 17 00:00:00 2001 From: MightyPork Date: Mon, 11 May 2015 02:54:16 +0200 Subject: [PATCH] onewire test project --- projects/onewire_test/Makefile | 141 ++++++ projects/onewire_test/lib/calc.h | 87 ++++ projects/onewire_test/lib/iopins.c | 276 +++++++++++ projects/onewire_test/lib/iopins.h | 213 +++++++++ projects/onewire_test/lib/onewire.h | 235 ++++++++++ projects/onewire_test/lib/stream.c | 213 +++++++++ projects/onewire_test/lib/stream.h | 100 ++++ projects/onewire_test/lib/uart.c | 678 ++++++++++++++++++++++++++++ projects/onewire_test/lib/uart.h | 253 +++++++++++ projects/onewire_test/main.c | 45 ++ projects/uart_linux_client/client | Bin 0 -> 10160 bytes 11 files changed, 2241 insertions(+) create mode 100644 projects/onewire_test/Makefile create mode 100644 projects/onewire_test/lib/calc.h create mode 100644 projects/onewire_test/lib/iopins.c create mode 100644 projects/onewire_test/lib/iopins.h create mode 100644 projects/onewire_test/lib/onewire.h create mode 100644 projects/onewire_test/lib/stream.c create mode 100644 projects/onewire_test/lib/stream.h create mode 100644 projects/onewire_test/lib/uart.c create mode 100644 projects/onewire_test/lib/uart.h create mode 100644 projects/onewire_test/main.c create mode 100755 projects/uart_linux_client/client diff --git a/projects/onewire_test/Makefile b/projects/onewire_test/Makefile new file mode 100644 index 0000000..dad113a --- /dev/null +++ b/projects/onewire_test/Makefile @@ -0,0 +1,141 @@ +## === CPU settings === +# CPU type +MCU = atmega328p +# CPU frequency +F_CPU = 16000000 +# Fuses +LFUSE = 0xFF +HFUSE = 0xDE +EFUSE = 0x05 + + +## === Source files === +# Main C file +MAIN = main.c +# Extra C files in this folder +LOCAL_SOURCE = + +# Library directory (with C files) +EXTRA_SOURCE_DIR = lib/ +# C files in the library directory +EXTRA_SOURCE_FILES = uart.c iopins.c stream.c + + +## === Programmer === +PROGRAMMER_TYPE = arduino +PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0 + + +## === C flags === + +CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR) +CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment +CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable +CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax +# CFLAGS += -lm ## Math +# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf +# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf +CFLAGS_BUILD = $(CFLAGS) -Os + + +# --------------------------------------------------------------------------- + +## Defined programs / locations +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +AVRSIZE = avr-size +AVRDUDE = avrdude + +## === File lists === +TARGET = $(strip $(basename $(MAIN))) +SRC1 = $(TARGET).c +SRC = $(SRC1) +EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES)) +SRC += $(EXTRA_SOURCE) +SRC += $(LOCAL_SOURCE) + +HEADERS = $(SRC:.c=.h) +OBJ = $(SRC:.c=.o) + + +## === File generation === +all: $(TARGET).hex size +pre: $(TARGET).pre + +%.hex: %.elf + $(OBJCOPY) -R .eeprom -O ihex $< $@ + +%.elf: $(SRC) + $(CC) $(CFLAGS_BUILD) $(SRC) --output $@ + +%.pre: $(SRC1) + $(CC) $(CFLAGS) -E $(SRC1) --output $@ + +%.eeprom: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ + +%.lst: %.elf + $(OBJDUMP) -S $< > $@ + +# Show debug info +debug: + @echo + @echo "Source files:" $(SRC) + @echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD) + @echo + + +# Disassemble the ELF +disassemble: $(TARGET).lst +dis: disassemble +lst: disassemble + +# Make eeprom file +eeprom: $(TARGET).eeprom + +# Show how big the resulting program is +size: $(TARGET).elf + $(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf + +# Clean all produced trash +clean: + rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \ + $(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \ + $(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \ + $(TARGET).eeprom + +# Clean all trash +purge: + rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ + + +## === avrdude === + +flash: $(TARGET).hex + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$< + +flashe: $(TARGET).eeprom + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$< + +shell: + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt + +fser: all flash ser + +ser: + gtkterm -p /dev/ttyUSB0 + +# === fuses === + +FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m + +fuses: + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \ + $(PROGRAMMER_ARGS) $(FUSE_STRING) +show_fuses: + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv + +set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m +set_default_fuses: fuses diff --git a/projects/onewire_test/lib/calc.h b/projects/onewire_test/lib/calc.h new file mode 100644 index 0000000..58f27bf --- /dev/null +++ b/projects/onewire_test/lib/calc.h @@ -0,0 +1,87 @@ +#pragma once + +// +// Bit and byte manipulation utilities +// + + +// --- Increment in range --- +// when overflown, wraps within range. Lower bound < upper bound. +// ..., upper bound excluded +#define inc_wrap(var, min, max) do { if ((var) >= (max - 1)) { (var) = (min); } else { (var)++; } } while(0) +// ..., upper bound included +#define inc_wrapi(var, min, max) inc_wrap((var), (min), (max) + 1) + + +// --- Decrement in range --- +// when underflown, wraps within range. Lower bound < upper bound. +// ..., upper bound excluded +#define dec_wrap(var, min, max) do { if ((var) <= (min)) { (var) = (max) - 1; } else { (var)--; } } while(0) +// ..., upper bound included +#define dec_wrapi(var, min, max) dec_wrap((var), (min), (max) + 1) + + +// --- Bit manipulation -- + +// Set bit +#define sbi(reg, bit) do { (reg) |= (1 << (uint8_t)(bit)); } while(0) + +// Clear bit +#define cbi(reg, bit) do { (reg) &= ~(1 << (uint8_t)(bit)); } while(0) + +// Get n-th bit +#define get_bit(reg, bit) (((reg) >> (uint8_t)(bit)) & 0x1) + +// Test n-th bit (Can't use bit_is_set, as it's redefined in sfr_def.h) +#define bit_is_high(reg, bit) get_bit(reg, bit) +#define bit_is_low(reg, bit) (!get_bit(reg, bit)) + +// Write value to n-th bit +#define set_bit(reg, bit, value) do { (reg) = ((reg) & ~(1 << (uint8_t)(bit))) | (((uint8_t)(value) & 0x1) << (uint8_t)(bit)); } while(0) + +// Invert n-th bit +#define toggle_bit(reg, bit) do { (reg) ^= (1 << (uint8_t)(bit)); } while(0) + + +// --- Bit manipulation with pointer to variable --- + +// Set n-th bit in pointee +#define sbi_p(reg_p, bit) do { (*(reg_p)) |= (1 << (uint8_t)(bit)); } while(0) +// Clear n-th bit in pointee +#define cbi_p(reg_p, bit) do { (*(reg_p)) &= ~(1 << (uint8_t)(bit)); } while(0) + +// Get n-th bit in pointee +#define get_bit_p(reg_p, bit) ((*(reg_p) >> (uint8_t)(bit)) & 0x1) + +// Test n-th bit in pointee (Can't use bit_is_set, as it's redefined in sfr_def.h) +#define bit_is_high_p(reg_p, bit) get_bit_p(reg_p, bit) +#define bit_is_low_p(reg_p, bit) (!get_bit_p(reg_p, bit)) + +// Write value to a bit in pointee +#define set_bit_p(reg_p, bit, value) do { *(reg_p) = (*(reg_p) & ~(1 << ((uint8_t)(bit) & 0x1))) | (((uint8_t)(value) & 0x1) << (uint8_t)(bit)); } while(0) +#define toggle_bit_p(reg_p, bit) do { *(reg_p) ^= (1 << (uint8_t)(bit)); } while(0) + + +// --- Nibble manipulation --- + +// Replace nibble in a byte +#define set_low_nibble(reg, value) do { (reg) = ((reg) & 0xF0) | ((uint8_t)(value) & 0xF); } while(0) +#define set_high_nibble(reg, value) do { (reg) = ((reg) & 0x0F) | (((uint8_t)(value) & 0xF) << 4); } while(0) + +#define set_low_nibble_p(reg_p, value) do { *(reg_p) = (*(reg_p) & 0xF0) | ((uint8_t)(value) & 0xF); } while(0) +#define set_high_nibble_p(reg_p, value) do { *(reg_p) = (*(reg_p) & 0x0F) | (((uint8_t)(value) & 0xF) << 4); } while(0) + +#define low_nibble(x) ((uint8_t)(x) & 0xF) +#define high_nibble(x) (((uint8_t)(x) & 0xF0) >> 4) + +// --- Range tests --- + +// Test if X is within low..high, regardless of bounds order +#define in_range(x, low, high) ((((low) < (high)) && ((x) >= (low) && (x) < (high))) || (((low) > (high)) && ((x) >= (high) && (x) < (low)))) +// ..., include greater bound +#define in_rangei(x, low, high) ((((low) <= (high)) && ((x) >= (low) && (x) <= (high))) || (((low) > (high)) && ((x) >= (high) && (x) <= (low)))) + +// Test if X in low..high, wrap around ends if needed. +#define in_range_wrap(x, low, high) ((((low) < (high)) && ((x) >= (low) && (x) < (high))) || (((low) > (high)) && ((x) >= (low) || (x) < (high)))) +// ..., include upper bound +#define in_range_wrapi(x, low, high) ((((low) <= (high)) && ((x) >= (low) && (x) <= (high))) || (((low) > (high)) && ((x) >= (low) || (x) <= (high)))) diff --git a/projects/onewire_test/lib/iopins.c b/projects/onewire_test/lib/iopins.c new file mode 100644 index 0000000..2b3934b --- /dev/null +++ b/projects/onewire_test/lib/iopins.c @@ -0,0 +1,276 @@ +#include +#include +#include + +#include "calc.h" +#include "iopins.h" + + +void set_dir_n(const uint8_t pin, const uint8_t d) +{ + switch(pin) { + case 0: set_dir(0, d); return; + case 1: set_dir(1, d); return; + case 2: set_dir(2, d); return; + case 3: set_dir(3, d); return; + case 4: set_dir(4, d); return; + case 5: set_dir(5, d); return; + case 6: set_dir(6, d); return; + case 7: set_dir(7, d); return; + case 8: set_dir(8, d); return; + case 9: set_dir(9, d); return; + case 10: set_dir(10, d); return; + case 11: set_dir(11, d); return; + case 12: set_dir(12, d); return; + case 13: set_dir(13, d); return; + case 14: set_dir(14, d); return; + case 15: set_dir(15, d); return; + case 16: set_dir(16, d); return; + case 17: set_dir(17, d); return; + case 18: set_dir(18, d); return; + case 19: set_dir(19, d); return; + case 20: set_dir(20, d); return; + case 21: set_dir(21, d); return; + } +} + +void as_input_n(const uint8_t pin) +{ + switch(pin) { + case 0: as_input(0); return; + case 1: as_input(1); return; + case 2: as_input(2); return; + case 3: as_input(3); return; + case 4: as_input(4); return; + case 5: as_input(5); return; + case 6: as_input(6); return; + case 7: as_input(7); return; + case 8: as_input(8); return; + case 9: as_input(9); return; + case 10: as_input(10); return; + case 11: as_input(11); return; + case 12: as_input(12); return; + case 13: as_input(13); return; + case 14: as_input(14); return; + case 15: as_input(15); return; + case 16: as_input(16); return; + case 17: as_input(17); return; + case 18: as_input(18); return; + case 19: as_input(19); return; + case 20: as_input(20); return; + case 21: as_input(21); return; + } +} + + +void as_input_pu_n(const uint8_t pin) +{ + switch(pin) { + case 0: as_input_pu(0); return; + case 1: as_input_pu(1); return; + case 2: as_input_pu(2); return; + case 3: as_input_pu(3); return; + case 4: as_input_pu(4); return; + case 5: as_input_pu(5); return; + case 6: as_input_pu(6); return; + case 7: as_input_pu(7); return; + case 8: as_input_pu(8); return; + case 9: as_input_pu(9); return; + case 10: as_input_pu(10); return; + case 11: as_input_pu(11); return; + case 12: as_input_pu(12); return; + case 13: as_input_pu(13); return; + case 14: as_input_pu(14); return; + case 15: as_input_pu(15); return; + case 16: as_input_pu(16); return; + case 17: as_input_pu(17); return; + case 18: as_input_pu(18); return; + case 19: as_input_pu(19); return; + case 20: as_input_pu(20); return; + case 21: as_input_pu(21); return; + } +} + + +void as_output_n(const uint8_t pin) +{ + switch(pin) { + case 0: as_output(0); return; + case 1: as_output(1); return; + case 2: as_output(2); return; + case 3: as_output(3); return; + case 4: as_output(4); return; + case 5: as_output(5); return; + case 6: as_output(6); return; + case 7: as_output(7); return; + case 8: as_output(8); return; + case 9: as_output(9); return; + case 10: as_output(10); return; + case 11: as_output(11); return; + case 12: as_output(12); return; + case 13: as_output(13); return; + case 14: as_output(14); return; + case 15: as_output(15); return; + case 16: as_output(16); return; + case 17: as_output(17); return; + case 18: as_output(18); return; + case 19: as_output(19); return; + case 20: as_output(20); return; + case 21: as_output(21); return; + } +} + +void set_pin_n(const uint8_t pin, const uint8_t v) +{ + switch(pin) { + case 0: set_pin(0, v); return; + case 1: set_pin(1, v); return; + case 2: set_pin(2, v); return; + case 3: set_pin(3, v); return; + case 4: set_pin(4, v); return; + case 5: set_pin(5, v); return; + case 6: set_pin(6, v); return; + case 7: set_pin(7, v); return; + case 8: set_pin(8, v); return; + case 9: set_pin(9, v); return; + case 10: set_pin(10, v); return; + case 11: set_pin(11, v); return; + case 12: set_pin(12, v); return; + case 13: set_pin(13, v); return; + case 14: set_pin(14, v); return; + case 15: set_pin(15, v); return; + case 16: set_pin(16, v); return; + case 17: set_pin(17, v); return; + case 18: set_pin(18, v); return; + case 19: set_pin(19, v); return; + case 20: set_pin(20, v); return; + case 21: set_pin(21, v); return; + } +} + +void pin_low_n(const uint8_t pin) +{ + switch(pin) { + case 0: pin_low(0); return; + case 1: pin_low(1); return; + case 2: pin_low(2); return; + case 3: pin_low(3); return; + case 4: pin_low(4); return; + case 5: pin_low(5); return; + case 6: pin_low(6); return; + case 7: pin_low(7); return; + case 8: pin_low(8); return; + case 9: pin_low(9); return; + case 10: pin_low(10); return; + case 11: pin_low(11); return; + case 12: pin_low(12); return; + case 13: pin_low(13); return; + case 14: pin_low(14); return; + case 15: pin_low(15); return; + case 16: pin_low(16); return; + case 17: pin_low(17); return; + case 18: pin_low(18); return; + case 19: pin_low(19); return; + case 20: pin_low(20); return; + case 21: pin_low(21); return; + } +} + +void pin_high_n(const uint8_t pin) +{ + switch(pin) { + case 0: pin_high(0); return; + case 1: pin_high(1); return; + case 2: pin_high(2); return; + case 3: pin_high(3); return; + case 4: pin_high(4); return; + case 5: pin_high(5); return; + case 6: pin_high(6); return; + case 7: pin_high(7); return; + case 8: pin_high(8); return; + case 9: pin_high(9); return; + case 10: pin_high(10); return; + case 11: pin_high(11); return; + case 12: pin_high(12); return; + case 13: pin_high(13); return; + case 14: pin_high(14); return; + case 15: pin_high(15); return; + case 16: pin_high(16); return; + case 17: pin_high(17); return; + case 18: pin_high(18); return; + case 19: pin_high(19); return; + case 20: pin_high(20); return; + case 21: pin_high(21); return; + } +} + + +void toggle_pin_n(const uint8_t pin) +{ + switch(pin) { + case 0: toggle_pin(0); return; + case 1: toggle_pin(1); return; + case 2: toggle_pin(2); return; + case 3: toggle_pin(3); return; + case 4: toggle_pin(4); return; + case 5: toggle_pin(5); return; + case 6: toggle_pin(6); return; + case 7: toggle_pin(7); return; + case 8: toggle_pin(8); return; + case 9: toggle_pin(9); return; + case 10: toggle_pin(10); return; + case 11: toggle_pin(11); return; + case 12: toggle_pin(12); return; + case 13: toggle_pin(13); return; + case 14: toggle_pin(14); return; + case 15: toggle_pin(15); return; + case 16: toggle_pin(16); return; + case 17: toggle_pin(17); return; + case 18: toggle_pin(18); return; + case 19: toggle_pin(19); return; + case 20: toggle_pin(20); return; + case 21: toggle_pin(21); return; + } +} + + +bool get_pin_n(const uint8_t pin) +{ + switch(pin) { + case 0: return get_pin(0); + case 1: return get_pin(1); + case 2: return get_pin(2); + case 3: return get_pin(3); + case 4: return get_pin(4); + case 5: return get_pin(5); + case 6: return get_pin(6); + case 7: return get_pin(7); + case 8: return get_pin(8); + case 9: return get_pin(9); + case 10: return get_pin(10); + case 11: return get_pin(11); + case 12: return get_pin(12); + case 13: return get_pin(13); + case 14: return get_pin(14); + case 15: return get_pin(15); + case 16: return get_pin(16); + case 17: return get_pin(17); + case 18: return get_pin(18); + case 19: return get_pin(19); + case 20: return get_pin(20); + case 21: return get_pin(21); + } + return false; +} + + +bool is_low_n(const uint8_t pin) +{ + return !get_pin_n(pin); +} + + +bool is_high_n(const uint8_t pin) +{ + return get_pin_n(pin); +} diff --git a/projects/onewire_test/lib/iopins.h b/projects/onewire_test/lib/iopins.h new file mode 100644 index 0000000..3cabadd --- /dev/null +++ b/projects/onewire_test/lib/iopins.h @@ -0,0 +1,213 @@ +#pragma once + +// +// * Utilities for pin aliasing / numbering. * +// +// Designed for Arduino. +// +// If you know the pin number beforehand, you can use the macros. +// +// If you need to use a variable for pin number, use the `_n` functions. +// They are much slower, so always check if you really need them +// - and they aren't fit for things where precise timing is required. +// + +#include +#include +#include + +#include "calc.h" + + +// type: pointer to port +typedef volatile uint8_t* PORT_P; + + +/** Pin numbering reference */ +#define D0 0 +#define D1 1 +#define D2 2 +#define D3 3 +#define D4 4 +#define D5 5 +#define D6 6 +#define D7 7 +#define D8 8 +#define D9 9 +#define D10 10 +#define D11 11 +#define D12 12 +#define D13 13 +#define D14 14 +#define D15 15 +#define D16 16 +#define D17 17 +#define D18 18 +#define D19 19 +#define D20 20 +#define D21 21 +#define A0 14 +#define A1 15 +#define A2 16 +#define A3 17 +#define A4 18 +#define A5 19 +#define A6 20 +#define A7 21 + + +#define _ddr(pin) _DDR_##pin +#define _pin(pin) _PIN_##pin +#define _pn(pin) _PN_##pin +#define _port(pin) _PORT_##pin + + +/** Set pin direction */ +#define set_dir(pin, d) set_bit( _ddr(pin), _pn(pin), d ) +void set_dir_n(const uint8_t pin, const uint8_t d); + + +/** Configure pin as input */ +#define as_input(pin) cbi( _ddr(pin), _pn(pin) ) +void as_input_n(const uint8_t pin); + + +/** Configure pin as input, with pull-up enabled */ +#define as_input_pu(pin) { as_input(pin); pin_high(pin); } +void as_input_pu_n(const uint8_t pin); + + +/** Configure pin as output */ +#define as_output(pin) sbi( _ddr(pin), _pn(pin) ) +void as_output_n(const uint8_t pin); + + +/** Write value to a pin */ +#define set_pin(pin, v) set_bit( _port(pin), _pn(pin), v ) +void set_pin_n(const uint8_t pin, const uint8_t v); + + +/** Write 0 to a pin */ +#define pin_low(pin) cbi( _port(pin), _pn(pin) ) +void pin_low_n(const uint8_t pin); + + +/** Write 1 to a pin */ +#define pin_high(pin) sbi( _port(pin), _pn(pin) ) +void pin_high_n(const uint8_t pin); + + +/** Toggle a pin state */ +#define toggle_pin(pin) sbi( _pin(pin), _pn(pin) ) +void toggle_pin_n(const uint8_t pin); + + +/** Read a pin value */ +#define get_pin(pin) get_bit( _pin(pin), _pn(pin) ) +bool get_pin_n(const uint8_t pin); + + +/** CHeck if pin is low */ +#define is_low(pin) (get_pin(pin) == 0) +bool is_low_n(const uint8_t pin); + + +/** CHeck if pin is high */ +#define is_high(pin) (get_pin(pin) != 0) +bool is_high_n(const uint8_t pin); + + + +// Helper macros + +#define _PORT_0 PORTD +#define _PORT_1 PORTD +#define _PORT_2 PORTD +#define _PORT_3 PORTD +#define _PORT_4 PORTD +#define _PORT_5 PORTD +#define _PORT_6 PORTD +#define _PORT_7 PORTD +#define _PORT_8 PORTB +#define _PORT_9 PORTB +#define _PORT_10 PORTB +#define _PORT_11 PORTB +#define _PORT_12 PORTB +#define _PORT_13 PORTB +#define _PORT_14 PORTC +#define _PORT_15 PORTC +#define _PORT_16 PORTC +#define _PORT_17 PORTC +#define _PORT_18 PORTC +#define _PORT_19 PORTC +#define _PORT_20 PORTC +#define _PORT_21 PORTC + +#define _PIN_0 PIND +#define _PIN_1 PIND +#define _PIN_2 PIND +#define _PIN_3 PIND +#define _PIN_4 PIND +#define _PIN_5 PIND +#define _PIN_6 PIND +#define _PIN_7 PIND +#define _PIN_8 PINB +#define _PIN_9 PINB +#define _PIN_10 PINB +#define _PIN_11 PINB +#define _PIN_12 PINB +#define _PIN_13 PINB +#define _PIN_14 PINC +#define _PIN_15 PINC +#define _PIN_16 PINC +#define _PIN_17 PINC +#define _PIN_18 PINC +#define _PIN_19 PINC +#define _PIN_20 PINC +#define _PIN_21 PINC + +#define _DDR_0 DDRD +#define _DDR_1 DDRD +#define _DDR_2 DDRD +#define _DDR_3 DDRD +#define _DDR_4 DDRD +#define _DDR_5 DDRD +#define _DDR_6 DDRD +#define _DDR_7 DDRD +#define _DDR_8 DDRB +#define _DDR_9 DDRB +#define _DDR_10 DDRB +#define _DDR_11 DDRB +#define _DDR_12 DDRB +#define _DDR_13 DDRB +#define _DDR_14 DDRC +#define _DDR_15 DDRC +#define _DDR_16 DDRC +#define _DDR_17 DDRC +#define _DDR_18 DDRC +#define _DDR_19 DDRC +#define _DDR_20 DDRC +#define _DDR_21 DDRC + +#define _PN_0 0 +#define _PN_1 1 +#define _PN_2 2 +#define _PN_3 3 +#define _PN_4 4 +#define _PN_5 5 +#define _PN_6 6 +#define _PN_7 7 +#define _PN_8 0 +#define _PN_9 1 +#define _PN_10 2 +#define _PN_11 3 +#define _PN_12 4 +#define _PN_13 5 +#define _PN_14 0 +#define _PN_15 1 +#define _PN_16 2 +#define _PN_17 3 +#define _PN_18 4 +#define _PN_19 5 +#define _PN_20 6 +#define _PN_21 7 diff --git a/projects/onewire_test/lib/onewire.h b/projects/onewire_test/lib/onewire.h new file mode 100644 index 0000000..f0fd2c0 --- /dev/null +++ b/projects/onewire_test/lib/onewire.h @@ -0,0 +1,235 @@ +#pragma once + +#include +#include +#include +#include + +#include "lib/iopins.h" +#include "lib/uart.h" +#include "lib/stream.h" + +#define SKIP_ROM 0xCC +#define CONVERT_T 0x44 +#define READ_SCRATCHPAD 0xBE + + +/** Perform bus reset. Returns true if any device is connected */ +bool ow_reset(const uint8_t pin) +{ + as_output_n(pin); + pin_low_n(pin); + _delay_us(480); + + as_input_pu_n(pin); + _delay_us(70); + + const bool a = get_pin_n(pin); + + _delay_us(410); + + return a; +} + + +/** Send a single bit */ +void ow_tx_bit(const uint8_t pin, const bool bit) +{ + as_output_n(pin); + pin_low_n(pin); + + if (bit) { + _delay_us(6); + as_input_pu_n(pin); + _delay_us(64); + } else { + _delay_us(60); + as_input_pu_n(pin); + _delay_us(10); + } +} + + +/** Send a single byte */ +void ow_send(const uint8_t pin, const uint8_t byte) +{ + for (uint8_t i = 0; i < 8; i++) + { + ow_tx_bit(pin, (byte >> i) & 0x01); + } +} + + +/** Read a single bit */ +bool ow_rx_bit(const uint8_t pin) +{ + as_output_n(pin); + pin_low_n(pin); + _delay_us(6); + + as_input_pu_n(pin); + _delay_us(9); + + const bool a = get_pin_n(pin); + + _delay_us(55); + + return a; +} + + +/** Read a single byte */ +uint8_t ow_read(const uint8_t pin) +{ + uint8_t byte = 0; + + for (uint8_t i = 0; i < 8; i++) + { + byte = (byte >> 1) | (ow_rx_bit(pin) << 7); + } + + return byte; +} + + +/** Wait until the device is ready. Returns false on timeout */ +bool ow_wait_ready(const uint8_t pin) +{ + uint16_t timeout = 700; + as_input_pu_n(pin); + + while (--timeout > 0) + { + if (is_high_n(pin)) return true; + _delay_ms(1); + } + + return false; +} + + +/** Read bytes into an array */ +void ow_read_arr(const uint8_t pin, uint8_t* array, const uint8_t count) +{ + for (uint8_t i = 0; i < count; i++) + { + array[i] = ow_read(pin); + } +} + + + +// ---------- CRC utils ---------- + +/* + Dallas 1-wire CRC routines for Arduino with examples of usage. + The 16-bit routine is new. + The 8-bit routine is from http://github.com/paeaetech/paeae/tree/master/Libraries/ds2482/ + + Copyright (C) 2010 Kairama Inc + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +// Dallas 1-wire 16-bit CRC calculation. Developed from Maxim Application Note 27. + +/** Compute a CRC16 checksum */ +uint16_t crc16( uint8_t *data, uint8_t len) +{ + uint16_t crc = 0; + + for (uint8_t i = 0; i < len; i++) + { + uint8_t inbyte = data[i]; + for (uint8_t j = 0; j < 8; j++) + { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc = crc >> 1; + if (mix) + crc = crc ^ 0xA001; + + inbyte = inbyte >> 1; + } + } + return crc; +} + + +// The 1-Wire CRC scheme is described in Maxim Application Note 27: +// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" + +/** Compute a CRC8 checksum */ +uint8_t crc8(uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + + for (uint8_t i = 0; i < len; i++) + { + uint8_t inbyte = addr[i]; + for (uint8_t j = 0; j < 8; j++) + { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) + crc ^= 0x8C; + + inbyte >>= 1; + } + } + + return crc; +} + + +// --- utils for DS1820 --- + +#define TEMP_ERROR -32768 + +/** Read temperature in 0.0625°C, or TEMP_ERROR on error */ +int16_t ds1820_read_temp(uint8_t pin) +{ + ow_send(pin, READ_SCRATCHPAD); + uint8_t bytes[9]; + ow_read_arr(pin, bytes, 9); + + put_nl(uart); + + uint8_t crc = crc8(bytes, 8); + if (crc != bytes[8]) { + return TEMP_ERROR; + } else { + int16_t a = ((bytes[1] << 8) | bytes[0]) >> 1; + a = a << 4; + a += (16 - bytes[6]) & 0x0F; + a -= 0x04; + + return a; + } +} + +/** Read temperature in 0.1°C, or TEMP_ERROR on error */ +int16_t ds1820_read_temp_c(uint8_t pin) +{ + int32_t temp = ds1820_read_temp(pin); + + if (temp == TEMP_ERROR) + return TEMP_ERROR; + + temp *= 625; + uint16_t rem = temp % 1000; + temp /= 1000; + if (rem >= 500) temp++; + + return (int16_t) temp; +} + diff --git a/projects/onewire_test/lib/stream.c b/projects/onewire_test/lib/stream.c new file mode 100644 index 0000000..9397b73 --- /dev/null +++ b/projects/onewire_test/lib/stream.c @@ -0,0 +1,213 @@ +#include +#include +#include + +#include "stream.h" +#include "calc.h" + + +static char tmpstr[20]; // buffer for number rendering + + +void put_str(const STREAM *p, char* str) +{ + char c; + while ((c = *str++)) { + p->tx(c); + } +} + + +void put_str_P(const STREAM *p, const char* str) +{ + char c; + while ((c = pgm_read_byte(str++))) { + p->tx(c); + } +} + + +static void _putnf(const STREAM *p, const uint8_t places); + + +/** Send signed int8 */ +void put_u8(const STREAM *p, const uint8_t num) +{ + utoa(num, tmpstr, 10); + put_str(p, tmpstr); +} + + +/** Send unsigned int8 */ +void put_i8(const STREAM *p, const int8_t num) +{ + itoa(num, tmpstr, 10); + put_str(p, tmpstr); +} + + + +/** Send unsigned int */ +void put_u16(const STREAM *p, const uint16_t num) +{ + utoa(num, tmpstr, 10); + put_str(p, tmpstr); +} + + +/** Send signed int */ +void put_i16(const STREAM *p, const int16_t num) +{ + itoa(num, tmpstr, 10); + put_str(p, tmpstr); +} + + +/** Send unsigned long */ +void put_u32(const STREAM *p, const uint32_t num) +{ + ultoa(num, tmpstr, 10); + put_str(p, tmpstr); +} + + +/** Send signed long */ +void put_i32(const STREAM *p, const int32_t num) +{ + ltoa(num, tmpstr, 10); + put_str(p, tmpstr); +} + + +/** Print number as hex */ +void _print_hex(const STREAM *p, uint8_t* start, uint8_t bytes) +{ + for (; bytes > 0; bytes--) { + uint8_t b = *(start + bytes - 1); + + for(uint8_t j = 0; j < 2; j++) { + uint8_t x = high_nibble(b); + b = b << 4; + if (x < 0xA) { + p->tx('0' + x); + } else { + p->tx('A' + (x - 0xA)); + } + } + } +} + + +/** Send unsigned int8 */ +void put_x8(const STREAM *p, const uint8_t num) +{ + _print_hex(p, (uint8_t*) &num, 1); +} + + +/** Send int as hex */ +void put_x16(const STREAM *p, const uint16_t num) +{ + _print_hex(p, (uint8_t*) &num, 2); +} + + +/** Send long as hex */ +void put_x32(const STREAM *p, const uint32_t num) +{ + _print_hex(p, (uint8_t*) &num, 4); +} + + +/** Send long long as hex */ +void put_x64(const STREAM *p, const uint64_t num) +{ + _print_hex(p, (uint8_t*) &num, 8); +} + + + +// float variant doesn't make sense for 8-bit int + +/** Send unsigned int as float */ +void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places) +{ + utoa(num, tmpstr, 10); + _putnf(p, places); +} + + +/** Send signed int as float */ +void put_i16f(const STREAM *p, const int16_t num, const uint8_t places) +{ + if (num < 0) { + p->tx('-'); + itoa(-num, tmpstr, 10); + } else { + itoa(num, tmpstr, 10); + } + + _putnf(p, places); +} + + +/** Send unsigned long as float */ +void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places) +{ + ultoa(num, tmpstr, 10); + _putnf(p, places); +} + + +/** Send signed long as float */ +void put_i32f(const STREAM *p, const int32_t num, const uint8_t places) +{ + if (num < 0) { + p->tx('-'); + ltoa(-num, tmpstr, 10); + } else { + ltoa(num, tmpstr, 10); + } + + _putnf(p, places); +} + + +/** Print number in tmp string as float with given decimal point position */ +void _putnf(const STREAM *p, const uint8_t places) +{ + // measure text length + uint8_t len = 0; + while(tmpstr[len] != 0) len++; + + int8_t at = len - places; + + // print virtual zeros + if (at <= 0) { + p->tx('0'); + p->tx('.'); + while(at <= -1) { + p->tx('0'); + at++; + } + at = -1; + } + + // print the number + uint8_t i = 0; + while(i < len) { + if (at-- == 0) { + p->tx('.'); + } + + p->tx(tmpstr[i++]); + } +} + + +/** Print CR LF */ +void put_nl(const STREAM *p) +{ + p->tx(13); + p->tx(10); +} diff --git a/projects/onewire_test/lib/stream.h b/projects/onewire_test/lib/stream.h new file mode 100644 index 0000000..8ed7979 --- /dev/null +++ b/projects/onewire_test/lib/stream.h @@ -0,0 +1,100 @@ +#pragma once + +// +// Streams -- in this library -- are instances of type STREAM. +// +// A stream can be used for receiving and sending bytes, generally +// it's a pipe to a device. +// +// They are designed for printing numbers and strings, but can +// also be used for general data transfer. +// +// Examples of streams: +// "uart.h" -> declares global variable "uart" which is a pointer to the UART stream +// "lcd.h" -> declares a global variable "lcd" (pointer to LCD scho stream) +// +// Streams help avoid code duplication, since the same functions can be used +// to format and print data to different device types. +// + +#include +#include +#include +#include + +/** Stream structure */ +typedef struct { + void (*tx) (uint8_t b); + uint8_t (*rx) (void); +} STREAM; + + +/** Print string into a stream */ +void put_str(const STREAM *p, char* str); + + +/** Print a programspace string into a stream */ +void put_str_P(const STREAM *p, const char* str); + + +/** Send signed int8 */ +#define put_char(p, c) (p)->tx((c)) +void put_u8(const STREAM *p, const uint8_t num); + + +/** Send unsigned int8 */ +void put_i8(const STREAM *p, const int8_t num); + + +/** Send unsigned int */ +void put_u16(const STREAM *p, const uint16_t num); + + +/** Send signed int */ +void put_i16(const STREAM *p, const int16_t num); + + +/** Send unsigned long */ +void put_u32(const STREAM *p, const uint32_t num); + + +/** Send signed long */ +void put_i32(const STREAM *p, const int32_t num); + + +/** Send unsigned int8 */ +void put_x8(const STREAM *p, const uint8_t num); + + +/** Send int as hex */ +void put_x16(const STREAM *p, const uint16_t num); + + +/** Send long as hex */ +void put_x32(const STREAM *p, const uint32_t num); + + +/** Send long long as hex */ +void put_x64(const STREAM *p, const uint64_t num); + + +// float variant doesn't make sense for 8-bit int + +/** Send unsigned int as float */ +void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places); + + +/** Send signed int as float */ +void put_i16f(const STREAM *p, const int16_t num, const uint8_t places); + + +/** Send unsigned long as float */ +void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places); + + +/** Send signed long as float */ +void put_i32f(const STREAM *p, const int32_t num, const uint8_t places); + + +/** Print CR LF */ +void put_nl(const STREAM *p); diff --git a/projects/onewire_test/lib/uart.c b/projects/onewire_test/lib/uart.c new file mode 100644 index 0000000..e2a477b --- /dev/null +++ b/projects/onewire_test/lib/uart.c @@ -0,0 +1,678 @@ +#include +#include +#include +#include +#include +#include + +#include "calc.h" +#include "uart.h" +#include "stream.h" + +// Shared stream instance +static STREAM _uart_singleton; +STREAM* uart; + + +void _uart_init_do(uint16_t ubrr) { + /*Set baud rate */ + UBRR0H = (uint8_t) (ubrr >> 8); + UBRR0L = (uint8_t) ubrr; + + // Enable Rx and Tx + UCSR0B = (1 << RXEN0) | (1 << TXEN0); + + // 8-bit data, 1 stop bit + UCSR0C = (0b11 << UCSZ00); + + _uart_singleton.tx = &uart_tx; + _uart_singleton.rx = &uart_rx; + + uart = &_uart_singleton; +} + + +/** Enable or disable RX ISR */ +void uart_isr_rx(bool yes) +{ + set_bit(UCSR0B, RXCIE0, yes); +} + + +/** Enable or disable TX ISR (1 byte is sent) */ +void uart_isr_tx(bool yes) +{ + set_bit(UCSR0B, TXCIE0, yes); +} + + +/** Enable or disable DRE ISR (all is sent) */ +void uart_isr_dre(bool yes) +{ + set_bit(UCSR0B, UDRIE0, yes); +} + + +/** Send byte over UART */ +void uart_tx(uint8_t data) +{ + // Wait for transmit buffer + while (!uart_tx_ready()); + // send it + UDR0 = data; +} + + +/** Receive one byte over UART */ +uint8_t uart_rx() +{ + // Wait for data to be received + while (!uart_rx_ready()); + // Get and return received data from buffer + return UDR0; +} + + +/** Send string over UART */ +void uart_puts(const char* str) +{ + while (*str) { + uart_tx(*str++); + } +} + + +/** Send progmem string over UART */ +void uart_puts_P(const char* str) +{ + char c; + while ((c = pgm_read_byte(str++))) { + uart_tx(c); + } +} + + +/** Clear receive buffer */ +void uart_flush() +{ + uint8_t dummy; + while (bit_is_high(UCSR0A, RXC0)) { + dummy = UDR0; + } +} + + +// ------------- VT100 extension -------------- + + +void _vt_apply_style(); +void _vt_reset_attribs_do(); +void _vt_style_do(); +void _vt_color_do(); + + +void vt_goto(uint8_t x, uint8_t y) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, y+1); // one-based ! + uart_tx(';'); + put_u8(uart, x+1); + uart_tx('H'); +} + + +void vt_goto_x(uint8_t x) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, x+1); + uart_tx('`'); +} + + +void vt_goto_y(uint8_t y) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, y+1); + uart_tx('d'); +} + + +void vt_move(int8_t x, int8_t y) +{ + vt_move_x(x); + vt_move_y(y); +} + + +void vt_move_x(int8_t x) +{ + if (x < 0) { + vt_left(-x); + } else { + vt_right(x); + } +} + + +void vt_move_y(int8_t y) +{ + if (y < 0) { + vt_up(-y); + } else { + vt_down(y); + } +} + + +void vt_up(uint8_t y) +{ + if (y == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, y); + uart_tx('A'); +} + + +void vt_down(uint8_t y) +{ + if (y == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, y); + uart_tx('B'); +} + + +void vt_left(uint8_t x) +{ + if (x == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, x); + uart_tx('D'); +} + + +void vt_right(uint8_t x) +{ + if (x == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, x); + uart_tx('C'); +} + + +void vt_scroll(int8_t y) +{ + while (y < 0) { + uart_tx(27); + uart_tx('D'); // up + y++; + } + + while (y > 0) { + uart_tx(27); + uart_tx('M'); // down + y--; + } +} + + +void vt_scroll_set(uint8_t from, uint8_t to) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, from); + uart_tx(';'); + put_u8(uart, to); + uart_tx('r'); +} + + +void vt_scroll_reset() +{ + uart_tx(27); + uart_tx('['); + uart_tx('r'); +} + + + +typedef struct { + uint8_t flags; + uint8_t fg; + uint8_t bg; +} vt_style_t; + +vt_style_t saved_style; +vt_style_t current_style; + +void vt_save() +{ + uart_puts_P(PSTR("\x1B[s")); + + saved_style = current_style; +} + + +void vt_restore() +{ + uart_puts_P(PSTR("\x1B[u")); + + current_style = saved_style; +} + + +/** Disable all text attributes (excluding color) */ +void vt_attr_reset() +{ + current_style.flags = 0; + + _vt_reset_attribs_do(); + _vt_apply_style(); +} + + +/** Set color to white on black */ +void vt_color_reset() +{ + current_style.fg = VT_WHITE; + current_style.bg = VT_BLACK; + + _vt_color_do(); +} + + +/** Enable or disable a text attribute */ +void vt_attr(uint8_t attribute, bool on) +{ + // flags are powers of two + // so this can handle multiple OR'd flags + for(uint8_t c = 1; c <= VT_FAINT; c *= 2) { + if (attribute & c) { + if (on) { + current_style.flags |= c; + } else { + current_style.flags &= ~c; + } + } + } + + _vt_apply_style(); +} + + +/** Send style and color commands */ +void _vt_apply_style() +{ + _vt_reset_attribs_do(); + _vt_style_do(); + _vt_color_do(); +} + + +/** Set color 0..7 */ +void vt_color(uint8_t fg, uint8_t bg) +{ + current_style.fg = fg; + current_style.bg = bg; + _vt_color_do(); +} + + +/** Set FG color 0..7 */ +void vt_color_fg(uint8_t fg) +{ + current_style.fg = fg; + _vt_color_do(); +} + + +/** Set BG color 0..7 */ +void vt_color_bg(uint8_t bg) +{ + current_style.bg = bg; + _vt_color_do(); +} + + +/** Send reset command */ +inline void _vt_reset_attribs_do() +{ + uart_puts_P(PSTR("\x1B[m")); // reset +} + + +/** Send commands for text attribs */ +void _vt_style_do() +{ + if (current_style.flags & VT_BOLD) { + uart_puts_P(PSTR("\x1B[1m")); + } + + if (current_style.flags & VT_FAINT) { + uart_puts_P(PSTR("\x1B[2m")); + } + + if (current_style.flags & VT_ITALIC) { + uart_puts_P(PSTR("\x1B[3m")); + } + + if (current_style.flags & VT_UNDERLINE) { + uart_puts_P(PSTR("\x1B[4m")); + } + + if (current_style.flags & VT_BLINK) { + uart_puts_P(PSTR("\x1B[5m")); + } + + if (current_style.flags & VT_REVERSE) { + uart_puts_P(PSTR("\x1B[7m")); + } +} + + +/** Send commands for xolor */ +void _vt_color_do() +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, 30 + current_style.fg); + uart_tx(';'); + put_u8(uart, 40 + current_style.bg); + uart_tx('m'); +} + + +/** Insert blank lines febore the current line */ +void vt_insert_lines(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('L'); +} + + +/** Delete lines from the current line down */ +void vt_delete_lines(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('M'); +} + + +/** Insert empty characters at cursor */ +void vt_insert_chars(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('@'); +} + + +/** Delete characters at cursor */ +void vt_delete_chars(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('P'); +} + + +void vt_clear() +{ + uart_puts_P(PSTR("\x1B[2J")); +} + + +void vt_erase_forth() +{ + uart_puts_P(PSTR("\x1B[K")); +} + + +void vt_erase_back() +{ + uart_puts_P(PSTR("\x1B[1K")); +} + + +void vt_erase_line() +{ + uart_puts_P(PSTR("\x1B[2K")); +} + + +void vt_erase_above() +{ + uart_puts_P(PSTR("\x1B[1J")); +} + +void vt_erase_below() +{ + uart_puts_P(PSTR("\x1B[J")); +} + + +void vt_home() +{ + uart_puts_P(PSTR("\x1B[H")); +} + + +/** Initialize helper variables */ +void vt_init() +{ + vt_reset(); +} + + +/** Reset state and clear screen */ +void vt_reset() +{ + // reset color and attributes + vt_color_reset(); + vt_attr_reset(); + vt_scroll_reset(); + + // clear screen + vt_clear(); + + // go to top left + vt_home(); + + // overwrite saved state + vt_save(); +} + + + +// Assigned keyhandler +void (*_vt_kh)(uint8_t, bool) = NULL; + +/** Assign a key handler (later used with vt_handle_key) */ +void vt_set_key_handler(void (*handler)(uint8_t, bool)) +{ + _vt_kh = handler; +} + + +// state machine states +typedef enum { + GROUND = 0, + ESC = 1, + BR = 2, + O = 3, + WAITING_TILDE = 4 +} KSTATE; + +// code received before started to wait for a tilde +uint8_t _before_wtilde; +// current state +KSTATE _kstate = GROUND; + + + +void _vt_kh_abort() +{ + switch (_kstate) { + case ESC: + _vt_kh(VK_ESC, true); + break; + + case BR: + _vt_kh(VK_ESC, true); + _vt_kh('[', false); + break; + + case O: + _vt_kh(VK_ESC, true); + _vt_kh('O', false); + break; + + case WAITING_TILDE: + _vt_kh(VK_ESC, true); + _vt_kh('[', false); + vt_handle_key(_before_wtilde); + break; + + case GROUND: + // nop + break; + } + + _kstate = GROUND; +} + + +/** + * Handle a key received over UART + * Takes care of multi-byte keys and translates them to special + * constants. + */ +void vt_handle_key(uint8_t c) +{ + if (_vt_kh == NULL) return; + + switch (_kstate) { + case GROUND: + switch (c) { + case 27: + _kstate = ESC; + break; + + case VK_ENTER: + case VK_TAB: + case VK_BACKSPACE: + _vt_kh(c, true); + return; + + default: + _vt_kh(c, false); + return; + } + + break; // continue to next char + + case ESC: + switch (c) { + case '[': + _kstate = BR; + break; // continue to next char + + case 'O': + _kstate = O; + break; // continue to next char + + default: + // bad code + _vt_kh_abort(); + vt_handle_key(c); + return; + } + break; + + case BR: + switch (c) { + // arrows + case 65: + case 66: + case 67: + case 68: + _vt_kh(c, true); + _kstate = GROUND; + return; + + // ins del pgup pgdn + case 50: + case 51: + case 53: + case 54: + // wait for terminating tilde + _before_wtilde = c; + _kstate = WAITING_TILDE; + break; // continue to next char + + // bad key + default: + _vt_kh_abort(); + vt_handle_key(c); + return; + } + break; + + case O: + switch (c) { + // F keys + case 80: + case 81: + case 82: + case 83: + // home, end + case 72: + case 70: + _vt_kh(c, true); + _kstate = GROUND; + return; + + // bad key + default: + _vt_kh_abort(); + vt_handle_key(c); + return; + } + + case WAITING_TILDE: + if (c != '~') { + _vt_kh_abort(); + vt_handle_key(c); + return; + } else { + _vt_kh(_before_wtilde, true); + _kstate = GROUND; + return; + } + } + + // wait for next key + if (_kstate != GROUND) { + _delay_ms(2); + if (!uart_rx_ready()) { + // abort receiving + _vt_kh_abort(); + + } else { + vt_handle_key(uart_rx()); + } + } +} diff --git a/projects/onewire_test/lib/uart.h b/projects/onewire_test/lib/uart.h new file mode 100644 index 0000000..13b0775 --- /dev/null +++ b/projects/onewire_test/lib/uart.h @@ -0,0 +1,253 @@ +#pragma once + +// +// Utilities for UART communication. +// +// First, init uart with desired baud rate using uart_init(baud). +// Then enable interrupts you want with uart_isr_XXX(). +// + +#include +#include +#include +#include +#include + +#include "stream.h" + +// Shared UART stream object +// Can be used with functions from stream.h once UART is initialized +extern STREAM* uart; + +/** Init UART for given baudrate */ +void _uart_init_do(uint16_t ubrr); // internal, needed for the macro. +#define uart_init(baud) _uart_init_do(F_CPU / 16 / (baud) - 1) + +/** Check if there's a byte in the RX register */ +#define uart_rx_ready() (0 != (UCSR0A & (1 << RXC0))) + +/** Check if transmission of everything is done */ +#define uart_tx_ready() (0 != (UCSR0A & (1 << UDRE0))) + + + +// Enable UART interrupts + +/** Enable or disable RX ISR */ +void uart_isr_rx(bool enable); + +/** Enable or disable TX ISR (1 byte is sent) */ +void uart_isr_tx(bool enable); + +/** Enable or disable DRE ISR (all is sent) */ +void uart_isr_dre(bool enable); + + + +// Basic IO + +/** Receive one byte over UART */ +uint8_t uart_rx(); + +/** Send byte over UART */ +#define uart_putc(data) uart_tx((data)) +void uart_tx(uint8_t data); + +/** Clear receive buffer */ +void uart_flush(); + + + +// Strings + +/** Send string over UART */ +void uart_puts(const char* str); + +/** Send progmem string over UART */ +void uart_puts_P(const char* str); + + + +// +// ANSI / VT100 utilities for UART +// +// To use this, first call uart_init(baud) and vt_init() +// To print stuff on the screen, use uart_puts() etc from uart.h +// + + +// INIT + +/** Initialize helper variables */ +void vt_init(); + +/** Reset state and clear screen */ +void vt_reset(); + + + +// CURSOR MOVE + +/** Move cursor to top left corner */ +void vt_home(); + +/** Jump to a location on the screen */ +void vt_goto(uint8_t x, uint8_t y); + +/** Jump to given X, keep Y */ +void vt_goto_x(uint8_t x); + +/** Jump to given Y, keep X */ +void vt_goto_y(uint8_t y); + +/** Move cursor relative to current location */ +void vt_move(int8_t x, int8_t y); + +/** Move cursor horizontally */ +void vt_move_x(int8_t x); + +/** Move cursor vertically */ +void vt_move_y(int8_t y); + +/** Move cursor up y cells */ +void vt_up(uint8_t y); + +/** Move cursor down y cells */ +void vt_down(uint8_t y); + +/** Move cursor left x cells */ +void vt_left(uint8_t x); + +/** Move cursor right x cells */ +void vt_right(uint8_t x); + + + +// SCROLLING + +/** Scroll y lines down (like up/down, but moves window if needed) */ +void vt_scroll(int8_t down); + +/** Set scrolling region (lines) */ +void vt_scroll_set(uint8_t from, uint8_t to); + + +/** Sets scrolling region to the entire screen. */ +void vt_scroll_reset(); + + +// COLOR + +#define VT_BLACK 0 +#define VT_RED 1 +#define VT_GREEN 2 +#define VT_YELLOW 3 +#define VT_BLUE 4 +#define VT_MAGENTA 5 +#define VT_CYAN 6 +#define VT_WHITE 7 + +/** Set color 0..7 */ +void vt_color(uint8_t fg, uint8_t bg); + +/** Set FG color 0..7 */ +void vt_color_fg(uint8_t fg); + +/** Set BG color 0..7 */ +void vt_color_bg(uint8_t bg); + +/** Set color to white on black */ +void vt_color_reset(); + + + +// STYLES + +#define VT_BOLD 1 +#define VT_UNDERLINE 2 +#define VT_BLINK 4 +#define VT_REVERSE 8 +#define VT_ITALIC 16 +#define VT_FAINT 32 + +/** Enable or disable a text attribute */ +void vt_attr(uint8_t attribute, bool on); + +/** Disable all text attributes (excluding color) */ +void vt_attr_reset(); + + + +// SAVE & RESTORE + +/** Save cursor position & text attributes */ +void vt_save(); + +/** Restore cursor to saved values */ +void vt_restore(); + + + +// MODIFY + + +/** Insert blank lines febore the current line */ +void vt_insert_lines(uint8_t count); + +/** Delete lines from the current line down */ +void vt_delete_lines(uint8_t count); + +/** Insert empty characters at cursor */ +void vt_insert_chars(uint8_t count); + +/** Delete characters at cursor */ +void vt_delete_chars(uint8_t count); + + + +// ERASING + +/** Clear the screen */ +void vt_clear(); + +/** Erase to the end of line */ +void vt_erase_forth(); + +/** Erase line to cursor */ +void vt_erase_back(); + +/** Erase entire line */ +void vt_erase_line(); + +/** Erase screen below the line */ +void vt_erase_above(); + +/** Erase screen above the line */ +void vt_erase_below(); + + + +// KEY HANDLER + +// Special keys from key handler +#define VK_LEFT 68 +#define VK_RIGHT 67 +#define VK_UP 65 +#define VK_DOWN 66 +#define VK_DELETE 51 +#define VK_INSERT 50 +#define VK_PGUP 53 +#define VK_PGDN 54 +#define VK_HOME 72 +#define VK_END 70 +#define VK_F1 80 +#define VK_F2 81 +#define VK_F3 82 +#define VK_F4 83 +#define VK_BACKSPACE 8 +#define VK_TAB 9 +#define VK_ENTER 13 +#define VK_ESC 27 + +void vt_handle_key(uint8_t c); +void vt_set_key_handler(void (*handler)(uint8_t, bool)); diff --git a/projects/onewire_test/main.c b/projects/onewire_test/main.c new file mode 100644 index 0000000..53e2ffa --- /dev/null +++ b/projects/onewire_test/main.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +#include "lib/iopins.h" +#include "lib/uart.h" +#include "lib/stream.h" +#include "lib/onewire.h" + +#define T 2 + +void main() +{ + uart_init(9600); + uart_puts_P(PSTR("*** OneWire test ***\r\n")); + + while(1) + { + _delay_ms(100); + + ow_reset(T); + ow_send(T, SKIP_ROM); + ow_send(T, CONVERT_T); + + if(!ow_wait_ready(T)) { + uart_puts_P(PSTR("Wait timeout!\r\n")); + continue; + } + + ow_reset(T); + ow_send(T, SKIP_ROM); + + int16_t temp = ds1820_read_temp_c(T); + + if (temp == TEMP_ERROR) { + uart_puts_P(PSTR("Read error!\r\n")); + } else { + put_i16f(uart, temp, 1); + uart_puts_P(PSTR(" °C\r\n")); + } + } +} diff --git a/projects/uart_linux_client/client b/projects/uart_linux_client/client new file mode 100755 index 0000000000000000000000000000000000000000..02f9449a22ecd2d370135c0a762a783e3c0474da GIT binary patch literal 10160 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