-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/ws2811-usb' into raspi
- Loading branch information
Showing
27 changed files
with
9,391 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
bin | ||
obj | ||
|
||
.gdb_history | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
# Makefile for the KL26-based WS2811 USB dongle | ||
# | ||
# Kevin Cuzner | ||
# | ||
|
||
PROJECT = kl2-ws2811 | ||
|
||
# Project target | ||
CPU = cortex-m0plus | ||
|
||
# Source | ||
SRCDIRS = src | ||
GENSRCDIRS = src | ||
BINDIR = bin | ||
OBJDIR = obj | ||
GENDIR = obj/gen | ||
INCDIRS = include | ||
LDINCDIRS = | ||
CSRCDIRS = $(SRCDIRS) | ||
SSRCDIRS = $(SRCDIRS) | ||
SRC = $(foreach DIR,$(CSRCDIRS),$(wildcard $(DIR)/*.c)) | ||
GENSRC = $(foreach DIR,$(GENSRCDIRS),$(wildcard $(DIR)/*.c)) | ||
STORAGESRC = $(foreach DIR,$(CSRCDIRS),$(wildcard $(DIR)/*.storage.xml)) | ||
ASM = $(foreach DIR,$(SSRCDIRS),$(wildcard $(DIR)/*.s)) | ||
|
||
|
||
# Include directories | ||
INCLUDE = $(foreach DIR,$(INCDIRS),-I$(DIR)) -I$(GENDIR) -I. | ||
LDINCLUDE = $(foreach DIR,$(LDINCDIRS),-L$(DIR)) | ||
|
||
# Linker | ||
LSCRIPT = kl2-dev.ld | ||
|
||
# C Flags | ||
GCFLAGS = -std=gnu99 -Wall -fno-common -mthumb -mcpu=$(CPU) -DSTM32F103xB --specs=nosys.specs -g -Wa,-ahlms=$(addprefix $(OBJDIR)/,$(notdir $(<:.c=.lst))) -O3 | ||
GCFLAGS += $(INCLUDE) -DUSB_DEBUG | ||
CFLAGS += $(GCFLAGS) | ||
LDFLAGS += -T$(LSCRIPT) -mthumb -mcpu=$(CPU) -Wl,-Map,$(BINDIR)/$(PROJECT).map -nostartfiles | ||
LDFLAGS += $(LDINCLUDE) | ||
ASFLAGS += -mcpu=$(CPU) | ||
|
||
# Flashing | ||
OCDFLAGS = -f openocd/openocd.cfg | ||
|
||
# Tools | ||
CC = arm-none-eabi-gcc | ||
AS = arm-none-eabi-as | ||
AR = arm-none-eabi-ar | ||
LD = arm-none-eabi-ld | ||
OBJCOPY = arm-none-eabi-objcopy | ||
SIZE = arm-none-eabi-size --format=SysV | ||
OBJDUMP = arm-none-eabi-objdump | ||
OCD = openocd | ||
GDB = arm-none-eabi-gdb | ||
|
||
RM = rm -rf | ||
|
||
# Code Generation | ||
PYTHON = python3 | ||
SCRIPTDIR = ./scripts | ||
DESCRIPTORGEN = $(PYTHON) $(SCRIPTDIR)/descriptorgen.py | ||
|
||
GENERATE = | ||
|
||
|
||
# | ||
# Build Targets | ||
# | ||
|
||
all:: $(BINDIR)/$(PROJECT).bin $(BINDIR)/$(PROJECT).hex | ||
|
||
install: $(BINDIR)/$(PROJECT).bin $(BINDIR)/openocd.pid | ||
cat openocd/flash.cfg | nc localhost 4444 | ||
|
||
macros: | ||
$(CC) $(GCFLAGS) -dM -E - < /dev/null | ||
|
||
cleanBuild: clean | ||
|
||
clean: stop | ||
$(RM) $(BINDIR) | ||
$(RM) $(OBJDIR) | ||
|
||
size: | ||
$(SIZE) $(BINDIR)/$(PROJECT).elf | ||
|
||
# | ||
# Debug | ||
# | ||
|
||
start: $(BINDIR)/openocd.pid | ||
|
||
stop: | ||
-echo shutdown | nc localhost 4444 | ||
|
||
$(BINDIR)/openocd.pid: | ||
openocd/run-openocd-server.sh $(OCD) $@ | ||
|
||
gdb: | ||
$(GDB) -ex "target remote alarmpi:3333" $(BINDIR)/$(PROJECT).elf | ||
|
||
## Build process | ||
|
||
GENERATE_USB_DESCRIPTOR=USB_DESCRIPTOR | ||
GENERATE_USB_DESCRIPTOR_SRC=_gen_usb_desc.c | ||
GENERATE_USB_DESCRIPTOR_HDR=_gen_usb_desc.h | ||
|
||
OBJ := $(addprefix $(OBJDIR)/,$(notdir $(SRC:.c=.o))) | ||
OBJ += $(addprefix $(OBJDIR)/,$(notdir $(ASM:.s=.o))) | ||
ifneq ($(filter $(GENERATE), $(GENERATE_USB_DESCRIPTOR)),) | ||
GEN_OBJ += $(GENDIR)/$(GENERATE_USB_DESCRIPTOR_SRC:.c=.o) | ||
GEN_TARGETS += $(GENERATE_USB_DESCRIPTOR) | ||
endif | ||
ALL_OBJ := $(OBJ) $(GEN_OBJ) | ||
DEP := $(addprefix $(OBJDIR)/,$(notdir $(SRC:.c=.d))) | ||
|
||
# | ||
# Code generation | ||
# | ||
$(GENERATE_USB_DESCRIPTOR): | ||
@mkdir -p $(GENDIR) | ||
$(DESCRIPTORGEN) -os $(GENDIR)/$(GENERATE_USB_DESCRIPTOR_SRC) \ | ||
-oh $(GENDIR)/$(GENERATE_USB_DESCRIPTOR_HDR) \ | ||
$(GENSRC) | ||
|
||
|
||
$(BINDIR)/$(PROJECT).hex: $(BINDIR)/$(PROJECT).elf | ||
$(OBJCOPY) -R .stack -O ihex $(BINDIR)/$(PROJECT).elf $(BINDIR)/$(PROJECT).hex | ||
|
||
$(BINDIR)/$(PROJECT).bin: $(BINDIR)/$(PROJECT).elf | ||
$(OBJCOPY) -R .stack -O binary $(BINDIR)/$(PROJECT).elf $(BINDIR)/$(PROJECT).bin | ||
|
||
$(BINDIR)/$(PROJECT).elf: $(ALL_OBJ) | ||
@mkdir -p $(dir $@) | ||
$(CC) $(ALL_OBJ) $(LDFLAGS) -o $(BINDIR)/$(PROJECT).elf | ||
$(OBJDUMP) -D $(BINDIR)/$(PROJECT).elf > $(BINDIR)/$(PROJECT).lst | ||
$(SIZE) $(BINDIR)/$(PROJECT).elf | ||
|
||
|
||
# Generates compilation rules for the directory in $1 | ||
# | ||
# Note to self: The double-dollar sign escapes the $ so that it doesn't get | ||
# evaluated when this function is generated, but instead gets evaluated when | ||
# Make is actually making. | ||
define build_gcc_rules | ||
$$(OBJDIR)/%.o: $1/%.c Makefile | ||
@mkdir -p $$(dir $$@) | ||
$$(CC) $$(GCFLAGS) -MMD -c $$< -o $$@ | ||
endef | ||
define build_asm_rules | ||
$$(OBJDIR)/%.o: $1/%.s Makefile | ||
@mkdir -p $$(dir $$@) | ||
$$(AS) $$(ASFLAGS) -o $$@ $$< | ||
endef | ||
|
||
# Generate rules for each source directory | ||
$(foreach DIR,$(CSRCDIRS),$(eval $(call build_gcc_rules,$(DIR)))) | ||
$(foreach DIR,$(SSRCDIRS),$(eval $(call build_asm_rules,$(DIR)))) | ||
|
||
-include $(DEP) | ||
|
||
# Ensure generated objects get run first | ||
$(OBJ): | $(GEN_TARGETS) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# WS2811 USB Dongle | ||
|
||
This is USB dongle firmware specifically built for the christmas tree project. I | ||
originally was going to make a nice general dongle, but both my motivation and | ||
time ran out. Instead, I am going to use my | ||
[kl2-dev](https://github.com/kcuzner/kl2-dev) board with this firmware. The | ||
raspberry pi will be used to flash it, although I cannot actually compile the | ||
program on the raspberry pi with archlinuxarm, since the package is missing and | ||
I don't feel like waiting hours and hours to compile arm-none-eabi-gcc. | ||
|
||
## Hardware Specifics | ||
|
||
The kl2-dev dongle has the following hardware: | ||
|
||
- MKL26Z32VRM4 Kinetis KL26 microcontroller | ||
- A USB port (micro usb) | ||
- Every I/O broken out into a pin | ||
|
||
## Feature List | ||
|
||
- USB Driver ported from my STM32 adventures. | ||
- USB Descriptor Generation ported from the midi-fader project (WIP) | ||
- Custom protocol (for use with libusb) (WIP) | ||
|
||
## Building | ||
|
||
### Environment | ||
|
||
This project should live on the raspberry pi. The raspberry pi needs to have NFS | ||
or some other file sharing set up to a standard x86 desktop. | ||
|
||
### Prerequisites - Raspberry Pi | ||
|
||
- `make` | ||
- `openocd` | ||
|
||
### Prerequisites - Desktop PC | ||
|
||
- `arm-none-eabi-gcc` | ||
- `arm-none-eabi-binutils` | ||
- `python3` | ||
|
||
### Build | ||
|
||
On the desktop PC, execute the following to build the firmware: | ||
|
||
``` | ||
$ make | ||
``` | ||
|
||
### Installation | ||
|
||
On the raspberry pi, execute the following to install the firmware | ||
|
||
``` | ||
$ make install | ||
``` | ||
|
||
This will start an openocd server which will persist. To shut down this server, | ||
run: | ||
|
||
``` | ||
$ make stop | ||
``` | ||
|
||
### Debug | ||
|
||
After installation, an openocd server will be running. The makefile should be | ||
configured with the hostname of the raspberry pi. The following command should | ||
be executed on the desktop PC. Unlike my other projects, it will not | ||
automatically start the openocd server. | ||
|
||
``` | ||
$ make gdb | ||
``` | ||
|
||
## Theory of Operation | ||
|
||
This is meant to be a very simple device. It essentially provides a buffer that | ||
will be dumped into the WS2811 chain as bytes are received. The device has no | ||
knowledge of the topology of the LEDs and will blindly dump data into the chain. | ||
|
||
Data is received over USB and dumped into the chain as soon as it is received. | ||
Once a transfer ends or if there is a data underflow, the device will cease | ||
dumping data into the buffer until the next transfer begins. | ||
|
||
The performance goal of this project is that I can dump enough data for 50 LEDs | ||
into the device every 16ms or so. | ||
|
||
## Protocol | ||
|
||
The protocol is very simple. There are no additional setup requests beyond the | ||
standard USB ones and there are no additional descriptors. | ||
|
||
In order to change the color of the LEDs (including turning them off), the host | ||
PC should initiate a bulk write to Endpoint 1. The data shall have the following | ||
format: | ||
|
||
``` | ||
Byte 0: Red value for the first LED in the chain | ||
Byte 1: Green value for the first LED in the chain | ||
Byte 2: Blue value for the first LED in the chain | ||
Byte 3: Red value for the second LED in the chain | ||
Byte 4: Blue value for the second LED in the chain | ||
Byte 5: Green value for the second LED in the chain | ||
Byte 6: Red for ... | ||
... | ||
``` | ||
|
||
Each byte triple is for one LED, starting with the LED nearest to the | ||
microcontroller. The number of bytes written must be a multiple of three. If the | ||
bulk transfer has a length which is not a multiple of three, a STALL condition | ||
results although the data up to the last byte triple will be pushed out to the | ||
LEDs. | ||
|
||
In the interest of keeping things simple, there is no reporting of whether or | ||
not there is a data underflow. | ||
|
Oops, something went wrong.