Cleanup, reorganization
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
Pin definitions for Arduino (Pro Mini with ATmega328P)
|
||||
*/
|
||||
|
||||
#include "pins.h"
|
||||
|
||||
#define D0 D,0
|
||||
#define D1 D,1
|
||||
#define D2 D,2
|
||||
#define D3 D,3
|
||||
#define D4 D,4
|
||||
#define D5 D,5
|
||||
#define D6 D,6
|
||||
#define D7 D,7
|
||||
#define D8 B,0
|
||||
#define D9 B,1
|
||||
#define D10 B,2
|
||||
#define D11 B,3
|
||||
#define D12 B,4
|
||||
#define D13 B,5
|
||||
#define A0 C,0
|
||||
#define A1 C,1
|
||||
#define A2 C,2
|
||||
#define A3 C,3
|
||||
#define A4 C,4
|
||||
#define A5 C,5
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
General purpose calculation and bit manipulation utilities.
|
||||
*/
|
||||
|
||||
// if max, go to zero. Else increment.
|
||||
#define inc_wrap(var, max) do { if ((var) >= (max)) { (var)=0; } else { (var)++; } } while(0)
|
||||
|
||||
// If zero, go to max. Else decrement,
|
||||
#define dec_wrap(var, max) do { if ((var) > 0) { (var)--; } else { (var)=(max); } } while(0)
|
||||
|
||||
// Check if value is in range A..B or B..A
|
||||
#define in_range(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) < (low) || (x) > (high)))
|
||||
|
||||
// Check if value is in range A..B. If B < A, matches all outside B..A
|
||||
#define in_range_wrap(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) > (low) || (x) < (high)))
|
||||
|
||||
// === general bit manipulation with register ===
|
||||
#define set_bit(reg, bit) do { (reg) |= (1 << bit); } while(0)
|
||||
#define clear_bit(reg, bit) do { (reg) &= ~(1 << bit); } while(0)
|
||||
#define toggle_bit(reg, bit) do { (reg) ^= (1 << bit); } while(0)
|
||||
|
||||
#define sbi(reg, bit) set_bit(reg, bit)
|
||||
#define cbi(reg, bit) clear_bit(reg, bit)
|
||||
|
||||
#define read_bit(reg, bit) ((((uint8_t)(reg)) >> ((uint8_t)(bit))) & 0x1)
|
||||
#define write_bit(reg, bit, value) do { (reg) = (((reg) & ~(1 << bit)) | ((value & 0x1) << (bit))); } while(0)
|
||||
|
||||
|
||||
// general pin manipulation - with pointer to register
|
||||
#define set_bit_p(reg_p, bit) do { (*reg_p) |= (1 << bit); } while(0)
|
||||
#define clear_bit_p(reg_p, bit) do { (*reg_p) &= ~(1 << bit); } while(0)
|
||||
#define sbi_p(reg_p, bit) set_bit_p(reg_p, bit)
|
||||
#define cbi_p(reg_p, bit) clear_bit_p(reg_p, bit)
|
||||
#define read_bit_p(reg_p, bit) ((((uint8_t)(*reg_p)) >> ((uint8_t)(bit))) & 0x1)
|
||||
#define write_bit_p(reg_p, bit, value) do { (*reg_p) = (((*reg_p) & ~(1 << bit)) | ((value & 0x1) << (bit))); } while(0)
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
Some useful utilities for RGB color manipulation
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} xrgb_t;
|
||||
|
||||
typedef uint32_t rgb24_t;
|
||||
typedef uint16_t rgb16_t;
|
||||
typedef uint16_t rgb12_t;
|
||||
typedef uint8_t rgb6_t;
|
||||
|
||||
|
||||
#define xrgb(rr, gg, bb) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) }
|
||||
#define xrgb_r(c) ((uint8_t)(c.r))
|
||||
#define xrgb_g(c) ((uint8_t)(c.g))
|
||||
#define xrgb_b(c) ((uint8_t)(c.b))
|
||||
#define xrgb_rgb24(c) ((((rgb24_t)c.r) << 16) | (((rgb24_t)c.g) << 8) | (((rgb24_t)c.b)))
|
||||
#define xrgb_rgb15(c) (((((rgb15_t)c.r) & 0xF8) << 7) | ((((rgb15_t)c.g) & 0xF8) << 2) | ((((rgb15_t)c.b) & 0xF8) >> 3))
|
||||
#define xrgb_rgb12(c) (((((rgb12_t)c.r) & 0xF0) << 4) | ((((rgb12_t)c.g) & 0xF0)) | ((((rgb12_t)c.b) & 0xF0) >> 4))
|
||||
#define xrgb_rgb6(c) (((((rgb6_t)c.r) & 0xC0) >> 2) | ((((rgb6_t)c.g) & 0xC0) >> 4) | ((((rgb6_t)c.b) & 0xC0) >> 6))
|
||||
|
||||
|
||||
#define rgb24(r,g,b) ((rgb24_t) (((((rgb24_t)r) & 0xFF) << 16) | ((((rgb24_t)g) & 0xFF) << 8) | (((rgb24_t)b) & 0xFF)))
|
||||
#define rgb24_r(c) ((((rgb24_t) (c)) >> 16) & 0xFF)
|
||||
#define rgb24_g(c) ((((rgb24_t) (c)) >> 8) & 0xFF)
|
||||
#define rgb24_b(c) ((((rgb24_t) (c)) >> 0) & 0xFF)
|
||||
#define rgb24_xrgb(c) xrgb(rgb24_r(c), rgb24_g(c), rgb24_b(c))
|
||||
|
||||
|
||||
#define rgb15(r,g,b) ((rgb16_t) (((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F)))
|
||||
#define rgb15_r(c) ((((rgb15_t) (c)) & 0x7C00) >> 7)
|
||||
#define rgb15_g(c) ((((rgb15_t) (c)) & 0x3E0) >> 2)
|
||||
#define rgb15_b(c) ((((rgb15_t) (c)) & 0x1F) << 3)
|
||||
#define rgb15_xrgb(c) xrgb(rgb15_r(c), rgb15_g(c), rgb15_b(c))
|
||||
#define rgb15_rgb24(c) rgb24(rgb15_r(c), rgb15_g(c), rgb15_b(c))
|
||||
|
||||
|
||||
#define rgb12(r,g,b) ((rgb12_t) (((r & 0xF) << 8) | ((g & 0xF) << 4) | (b & 0xF)))
|
||||
#define rgb12_r(c) ((((rgb12_t) (c)) & 0xF00) >> 4)
|
||||
#define rgb12_g(c) (((rgb12_t) (c)) & 0xF0)
|
||||
#define rgb12_b(c) (((r(rgb12_t) (c)gb) & 0x0F) << 4)
|
||||
#define rgb12_xrgb(c) xrgb(rgb12_r(c), rgb12_g(c), rgb12_b(c))
|
||||
#define rgb12_rgb24(c) rgb24(rgb12_r(c), rgb12_g(c), rgb12_b(c))
|
||||
|
||||
|
||||
#define rgb6(r,g,b) ((rgb6_t) (((r & 3) << 4) | ((g & 3) << 2) | (b & 3)))
|
||||
#define rgb6_r(c) ((((rgb6_t) (c)) & 0x30) << 2)
|
||||
#define rgb6_g(c) ((((rgb6_t) (c)) & 0xC) << 4)
|
||||
#define rgb6_b(c) ((((rgb6_t) (c)) & 0x3) << 6)
|
||||
#define rgb6_xrgb(c) xrgb(rgb6_r(c), rgb6_g(c), rgb6_b(c))
|
||||
#define rgb6_rgb24(c) rgb24(rgb6_r(c), rgb6_g(c), rgb6_b(c))
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
/** Weird constructs for the compiler */
|
||||
|
||||
// general macros
|
||||
#define SECTION(pos) __attribute__((naked, used, section(pos)))
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
Functions for precise delays (nanoseconds / cycles)
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <util/delay_basic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Convert nanoseconds to cycle count */
|
||||
#define ns2cycles(ns) ( (ns) / (1000000000L / (signed long) F_CPU) )
|
||||
|
||||
/** Wait c cycles */
|
||||
#define delay_c(c) (((c) > 0) ? __builtin_avr_delay_cycles(c) : __builtin_avr_delay_cycles(0))
|
||||
|
||||
/** Wait n nanoseconds, plus c cycles */
|
||||
#define delay_ns_c(ns, c) delay_c(ns2cycles(ns) + (c))
|
||||
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
This file provides macros for pin manipulation.
|
||||
|
||||
You can define your application pins like so:
|
||||
|
||||
// Led at PORTB, pin 1
|
||||
#define LED B,1
|
||||
|
||||
// Switch at PORTD, pin 7
|
||||
#define SW1 D,7
|
||||
|
||||
Now you can use macros from this file to wirh with the pins, eg:
|
||||
|
||||
as_output(LED);
|
||||
as_input(SW1);
|
||||
pullup_on(SW1);
|
||||
|
||||
toggle_pin(LED);
|
||||
while (pin_is_low(SW1));
|
||||
|
||||
- The macros io2XXX() can be used to get literal name of register associated with the pin.
|
||||
io2n() provides pin number.
|
||||
- The XXX_aux() macros are internal and should not be used elsewhere.
|
||||
- The io_pack() macro is used to pass pin (io) to other macro without expanding it.
|
||||
|
||||
Additionaly, there's general-purpose bit-manipulation macros (set_bit, clear_bit etc.).
|
||||
Those work with register name and pin number, not the "io" format (#define LED2 D,3).
|
||||
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "calc.h"
|
||||
|
||||
|
||||
// Get particular register associated with the name X (eg. D -> PORTD)
|
||||
#define reg_ddr(X) DDR ## X
|
||||
#define reg_port(X) PORT ## X
|
||||
#define reg_pin(X) PIN ## X
|
||||
|
||||
#define io2ddr_aux(reg, bit) reg_ddr(reg)
|
||||
#define io2ddr(io) io2ddr_aux(io)
|
||||
#define io2port_aux(reg, bit) reg_port(reg)
|
||||
#define io2port(io) io2port_aux(io)
|
||||
#define io2pin_aux(reg, bit) reg_pin(reg)
|
||||
#define io2pin(io) io2pin_aux(io)
|
||||
#define io2n_aux(reg, bit) bit
|
||||
#define io2n(io) io2n_aux(io)
|
||||
|
||||
#define io_pack(port, bit) port, bit
|
||||
|
||||
|
||||
// pointer to port
|
||||
typedef volatile uint8_t* PORT_P;
|
||||
// number of bit in port
|
||||
typedef uint8_t BIT_N;
|
||||
|
||||
|
||||
// === pin manipulation ===
|
||||
#define set_pin_aux(port, bit) set_bit(reg_port(port), bit)
|
||||
#define clear_pin_aux(port, bit) clear_bit(reg_port(port), bit)
|
||||
#define read_pin_aux(port, bit) read_bit(reg_pin(port), bit)
|
||||
#define write_pin_aux(port, bit, value) write_bit(reg_port(port), bit, value)
|
||||
#define toggle_pin_aux(port, bit) set_bit(reg_pin(port), bit)
|
||||
|
||||
|
||||
#define set_pin(io) set_pin_aux(io)
|
||||
#define pin_high(io) set_pin_aux(io)
|
||||
|
||||
#define clear_pin(io) clear_pin_aux(io)
|
||||
#define pin_low(io) clear_pin_aux(io)
|
||||
|
||||
#define read_pin(io) read_pin_aux(io)
|
||||
|
||||
#define pin_is_low(io) !read_pin_aux(io)
|
||||
#define pin_is_high(io) read_pin_aux(io)
|
||||
|
||||
#define write_pin(io, value) write_pin_aux(io, value)
|
||||
|
||||
#define toggle_pin(io) toggle_pin_aux(io)
|
||||
|
||||
|
||||
|
||||
// setting pin direction
|
||||
#define as_input_aux(port, bit) clear_bit(reg_ddr(port), bit)
|
||||
#define as_output_aux(port, bit) set_bit(reg_ddr(port), bit)
|
||||
#define set_dir_aux(port, bit, dir) write_bit(reg_ddr(port), bit, dir)
|
||||
|
||||
|
||||
#define as_input(io) as_input_aux(io)
|
||||
#define as_output(io) as_output_aux(io)
|
||||
#define set_dir(io, dir) set_dir_aux(io, dir)
|
||||
|
||||
|
||||
|
||||
// setting pullup
|
||||
#define pullup_enable_aux(port, bit) set_bit(reg_port(port), bit)
|
||||
#define pullup_disable_aux(port, bit) clear_bit(reg_port(port), bit)
|
||||
#define set_pullup_aux(port, bit, on) write_bit(reg_port(port), bit, on)
|
||||
|
||||
|
||||
#define pullup_enable(io) pullup_enable_aux(io)
|
||||
#define pullup_on(io) pullup_enable_aux(io)
|
||||
|
||||
#define pullup_disable(io) pullup_disable_aux(io)
|
||||
#define pullup_off(io) pullup_disable_aux(io)
|
||||
|
||||
#define set_pullup(io, on) set_pullup_aux(io, on)
|
||||
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
Utils for driving a WS2812 (WS2812B) RGB LED strips.
|
||||
|
||||
It's implemented as macros to avoid overhead when passing values, and to
|
||||
enable driving multiple strips at once. There is over 1us of free time between
|
||||
the colors, which can be used for some processing or color computation.
|
||||
|
||||
To avoid bloating your code, try to reduce the nuýmber of invocations -
|
||||
compute color and then send it.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "pins.h"
|
||||
#include "nsdelay.h"
|
||||
#include "colors.h"
|
||||
|
||||
/* Driver code for WS2812B */
|
||||
|
||||
// --- timing constraints (NS) ---
|
||||
|
||||
#ifndef WS_T_1H
|
||||
#define WS_T_1H 700
|
||||
#endif
|
||||
|
||||
#ifndef WS_T_1L
|
||||
#define WS_T_1L 150
|
||||
#endif
|
||||
|
||||
#ifndef WS_T_0H
|
||||
#define WS_T_0H 150
|
||||
#endif
|
||||
|
||||
#ifndef WS_T_0L
|
||||
#define WS_T_0L 700
|
||||
#endif
|
||||
|
||||
#ifndef WS_T_LATCH
|
||||
#define WS_T_LATCH 6000
|
||||
#endif
|
||||
|
||||
|
||||
/** Wait long enough for the colors to show */
|
||||
#define ws_show() do { delay_ns_c(WS_T_LATCH, 0); } while(0)
|
||||
|
||||
|
||||
/** Send one byte to the RGB strip */
|
||||
#define ws_send_byte(io, bb) do { \
|
||||
for (volatile int8_t __wsba_i = 7; __wsba_i >= 0; --__wsba_i) { \
|
||||
if ((bb) & (1 << __wsba_i)) { \
|
||||
pin_high(io_pack(io)); delay_ns_c(WS_T_1H, -2); \
|
||||
pin_low(io_pack(io)); delay_ns_c(WS_T_1L, -10); \
|
||||
} else { \
|
||||
pin_high(io_pack(io)); delay_ns_c(WS_T_0H, -2); \
|
||||
pin_low(io_pack(io)); delay_ns_c(WS_T_0L, -10); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
/** Send R,G,B color to the strip */
|
||||
#define ws_send_rgb(io, r, g, b) do { \
|
||||
ws_send_byte(io_pack(io), g); \
|
||||
ws_send_byte(io_pack(io), r); \
|
||||
ws_send_byte(io_pack(io), b); \
|
||||
} while(0)
|
||||
|
||||
/** Send a RGB struct */
|
||||
#define ws_send_xrgb(io, xrgb) ws_send_rgb(io_pack(io), (xrgb).r, (xrgb).g, (xrgb).b)
|
||||
|
||||
/** Send color hex */
|
||||
#define ws_send_rgb24(io, rgb) ws_send_rgb(io_pack(io), rgb24_r(rgb), rgb24_g(rgb), rgb24_b(rgb))
|
||||
#define ws_send_rgb15(io, rgb) ws_send_rgb(io_pack(io), rgb15_r(rgb), rgb15_g(rgb), rgb15_b(rgb))
|
||||
#define ws_send_rgb12(io, rgb) ws_send_rgb(io_pack(io), rgb12_r(rgb), rgb12_g(rgb), rgb12_b(rgb))
|
||||
#define ws_send_rgb6(io, rgb) ws_send_rgb(io_pack(io), rgb6_r(rgb), rgb6_g(rgb), rgb6_b(rgb))
|
||||
Reference in New Issue
Block a user