Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,11 @@
*~
*.ods
*.log

.DS_Store
firmware/p600firmware.bin

firmware/p600firmware.elf

firmware/p600firmware.hex

firmware/p600firmware.lss

firmware/p600firmware.map

firmware/p600firmware.syx
/common/*~
/build
78 changes: 78 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
## How to build

At the time of writing, GCC-AVR 11 seems to be the optimal version to
use as it produces the smallest (working) firmware.

The general process is as follows:

* install all required dependencies: gcc-avr, avr-libc, cmake, make and python3.
* compile the code
* use one of the products for flashing

Compilation in a shell works like this:

```sh
mkdir -p build && cd build
cmake ..
make
```

`p600firmware.bin` and `p600firmware.syx` are the most relevant build
products for flashing via USB or MIDI, respectively. These files are
created by default. Try `make help` for a list of all available build
targets.

### Using docker or podman

The most flexible approach is to use a compiler toolchain inside a
dockerized Linux environment as this can easily build and set up on
all operating systems.

It is also possible to specify a certain compiler version and/or have
multiple versions readily available.

The Dockerfile supplied with the repository can be used to create a
Docker image based on Alpine Linux and provides gcc-avr, make and python3.

An overview of the several gcc-avr versions for several Alpine releases can be found [here](https://pkgs.alpinelinux.org/packages?name=gcc-avr&branch=&repo=&arch=&maintainer=).

```sh
# Build gcc 12 using Alpine Linux edge (default)
docker build -t avr-toolchain:12 .

# Build gcc 11 using Alpine Linux 3.16
docker build --build-arg ALPINE_VERSION=3.16 -t avr-toolchain:11 .

# Build gcc 10 using Alpine Linux 3.15
docker build --build-arg ALPINE_VERSION=3.15 -t avr-toolchain:10 .

# Compile project
docker run --rm -v $(pwd):/build avr-toolchain:11 \
sh -c "mkdir -p build && cd build && cmake .. && make"
```

### Building on MacOS

On MacOS, first set up a [Homebrew](https://brew.sh) environment.

By adding the
[homebrew-avr](https://github.com/osx-cross/homebrew-avr/) tap from
here, several GCC compiler versions can be installed.

`avr-gcc@10` and `avr-gcc@11` have been tested successfully on a M1
Macbook Air and should work on an Intel Macbook as well.

### Building on Linux

Depending on the used distribution, it can be hard to find a working
pre-packaged compiler toolchain.

On Debian for example, there is only GCC-AVR version 5 available by
default.

Fedora on the other hand offers modern GCC versions in their more
recent [releases](https://src.fedoraproject.org/rpms/avr-gcc).

### Building on Windows

Work in progress.
99 changes: 99 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
cmake_minimum_required(VERSION 3.11)

# AVR GCC toolchain (has to be set before project())
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_CXX_COMPILER avr-g++)
set(CMAKE_C_COMPILER avr-gcc)
set(CMAKE_ASM_COMPILER avr-gcc)

project(p600fw)
set(PRODUCT_NAME p600firmware)

# AVR chip configuration
set(F_CPU 16000000UL)
set(MCU at90usb1286)

# Pass defines to compiler
add_definitions(
-DF_CPU=${F_CPU}
)

add_compile_options(
-mmcu=${MCU} # MCU
-std=gnu99 # C99 standard
-O2 # optimize
-Wall # enable warnings
-gdwarf-2
-funsigned-char
-funsigned-bitfields
-fpack-struct
-fshort-enums
-Wstrict-prototypes
-fno-unroll-loops
-fno-inline-functions
-flto=auto
-fuse-linker-plugin
)

add_link_options(
-mmcu=${MCU}
-flto=auto
-Wl,-Map=p600firmware.map,--cref
-Wl,--relax
-lm
-Wl,--section-start=.updater=0x1e000
-Wl,--section-start=.nrww_misc=0x1ec00
-Wl,--section-start=.bootloader=0x1f000
)

include_directories(
common
firmware
)

file(GLOB SRC_FILES
"xnormidi/*.c"
"xnormidi/bytequeue/*.c"
"firmware/*.c"
"common/*.c"
)

# Generate list files
set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} -Wa,-adhlns=<OBJECT>.lst")

# Create one target for compiling
add_executable(${PRODUCT_NAME} EXCLUDE_FROM_ALL ${SRC_FILES})
set_target_properties(${PRODUCT_NAME} PROPERTIES SUFFIX .elf ADDITIONAL_CLEAN_FILES ${PRODUCT_NAME}.map)

# Call avr-size after building .elf file
add_custom_target(size ALL avr-size ${PRODUCT_NAME}.elf DEPENDS ${PRODUCT_NAME})

add_custom_command(
OUTPUT ${PRODUCT_NAME}.hex
COMMAND avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.hex
DEPENDS ${PRODUCT_NAME}
)
add_custom_target(hex DEPENDS ${PRODUCT_NAME}.hex)

add_custom_command(
OUTPUT ${PRODUCT_NAME}.lss
COMMAND avr-objdump -h -S -z ${PRODUCT_NAME}.elf > ${PRODUCT_NAME}.lss
DEPENDS ${PRODUCT_NAME}
)
add_custom_target(lss DEPENDS ${PRODUCT_NAME}.lss)

add_custom_command(
OUTPUT ${PRODUCT_NAME}.bin
COMMAND avr-objcopy -O binary -R .eeprom -R .fuse -R .lock -R .signature -R .updater -R .nrww_misc -R .bootloader ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.bin
DEPENDS ${PRODUCT_NAME}
)
add_custom_target(bin DEPENDS ${PRODUCT_NAME}.bin)

add_custom_command(
OUTPUT ${PRODUCT_NAME}.syx
COMMAND python3 "${CMAKE_SOURCE_DIR}/fw2syx/fw2syx.py" -o ${PRODUCT_NAME}.syx ${PRODUCT_NAME}.bin
DEPENDS bin
)
add_custom_target(syx ALL DEPENDS ${PRODUCT_NAME}.syx)

add_custom_target(sendsyx p600_send ${PRODUCT_NAME}.syx DEPENDS ${PRODUCT_NAME}.syx)
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ARG ALPINE_VERSION=edge
FROM alpine:${ALPINE_VERSION}

RUN apk --no-cache add avr-libc cmake gcc-avr make python3

WORKDIR /build