diff --git a/README.md b/README.md index 74221ce..f8d1494 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,11 @@ A video covering most of this information can be found at https://www.youtube.co +## Optional Mods ## + +* [LED mod](./mods/led_ring/README.md) + + ## License ## Copyright (C) 2018 Andrew Tait diff --git a/mods/README.md b/mods/README.md new file mode 100644 index 0000000..6925290 --- /dev/null +++ b/mods/README.md @@ -0,0 +1,5 @@ +# SC mods + +Optional modifications for the SC + +* [LED Ring Mod](./led_ring/README.md) diff --git a/mods/led_ring/README.md b/mods/led_ring/README.md new file mode 100644 index 0000000..71ad71b --- /dev/null +++ b/mods/led_ring/README.md @@ -0,0 +1,64 @@ +# LED Ring mod for SC + +This is an optional modification to add a LED ring to display the current platter position, like having a sticker on vinyl. + +[![Demo Video](https://img.youtube.com/vi/FGX4gD_Zo5w/0.jpg)](https://www.youtube.com/watch?v=FGX4gD_Zo5w) + + +Required hardware: + +* **ESP8266** (~$5) + + Used a dev board for easier development, but plain ESP chip should work too. + +* **LED ring** (WS2812 aka Neopixel, ~$10) + + The more LEDs the ring has, the more precise the angle can be displayed. Tested with 24 LEDs (15°/LED). + + Depending on your case: maximum diameter of ~10cm to fit into the default case. + + This mod will also work with an LED strip, it doesn't have to be an actual ring. + + [Supported protocols](https://nodemcu.readthedocs.io/en/release/modules/ws2812/): WS2812, WS2812b, APA104, SK6812 (RGB or RGBW) + + +## Steps + +* Flash the NodeMCU firmware, see [./firmware/README](./firmware/README.md) + +* Upload the LUA software, see [./software/README](./software/README.md) + +* Connect the hardware + + ``` + ┌──────────┐ + │ ESP8266 │ ┌───────────────┐ + ├──────────┤ │ WS2812 (LED) │ + ¦ .. ¦ ├───────────────┤ + ┤ D4 ├-------------┤ IN │ + ┤ 3.3V ├-------------┤ VCC │ + ┤ GND ├-------------┤ GND │ + ¦ .. ¦ └───────────────┘ + ┤ RxD0 ├----┐ ┌───────────────┐ + ┤ TxD0 ├ | │ J7 (SC1000) │ + ┤ GND ├----+---┐ ├───────────────┤ + ┤ 3.3V ├-┐ │ └--┤GND 3.3V ├-┐ + └──────────┘ | | ┤UART3 RX ├ | + | └------┤UART3 TX ├ | + | ┤ ├ | + | ┤ ├ | + | └───────────────┘ | + └---------------------------┘ + ``` + + +* Enable the mod in `settings.txt` + + ```ini + # 1 to enable LED ring mod, default 0 (disabled) + ledringenabled=1 + ``` + +* [Optional] Configure the LED color and pattern + + See [software/README](./software/README.md) diff --git a/mods/led_ring/firmware/README.md b/mods/led_ring/firmware/README.md new file mode 100644 index 0000000..9db8314 --- /dev/null +++ b/mods/led_ring/firmware/README.md @@ -0,0 +1,37 @@ +# Firmware for the ESP8266 + +Using LUA based NodeMCU firmware: https://nodemcu.readthedocs.io/en/release/ + + +## Download firmware + +Use the provided `./nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin` firmware. + +Or build and/or download your custom firmware: +* Docs: https://nodemcu.readthedocs.io/en/release/build/ +* Cloud build: https://nodemcu-build.com/ + + +This project requires the following modules: `file gpio net node tmr uart ws2812` + + +## Flashing firmware + +Easiest way is to use the python-based [esptool](https://github.com/espressif/esptool). + +`pip install esptool` + +`esptool.py --port /dev/ttyUSB0 write_flash 0x00000 ./nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin` +(Adjust the USB port to your actual one) + + +During next boot after successful flashing, the ESP should display a message similar to: +``` +NodeMCU custom build by frightanic.com + branch: 1.5.4.1-final + commit: b9436bdfa452c098d5cb42a352ca124c80b91b25 + SSL: true + modules: adc,file,gpio,http,i2c,net,node,rtctime,tmr,u8g,uart,wifi,ws2812,tls + build created on 2019-12-31 14:51 + powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32) +``` \ No newline at end of file diff --git a/mods/led_ring/firmware/nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin b/mods/led_ring/firmware/nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin new file mode 100644 index 0000000..2c1a031 Binary files /dev/null and b/mods/led_ring/firmware/nodemcu-1.5.4.1-final-14-modules-2019-12-31-14-52-16-float__adc_file_gpio_http_i2c_net_node_rtctime_tmr_u8g_uart_wifi_ws2812_tls.bin differ diff --git a/mods/led_ring/software/README.md b/mods/led_ring/software/README.md new file mode 100644 index 0000000..fe9e3f4 --- /dev/null +++ b/mods/led_ring/software/README.md @@ -0,0 +1,83 @@ +# Upload the software to ESP + + +* Adjust `config.lua` to your needs + + **Depending on the LED ring (or stripe):** + + ```lua + -- Number of LEDs + LED_COUNT = 24 + + -- 3 for RGB strips and 4 for RGBW strips + BYTES_PER_LED = 3 + ``` + + **Debug mode:** + + When active, the ESP will generate a _fake_ rotation signal by itself for demonstration and development purpose. + + ```lua + -- Enable demo signal to show a hard coded LED rotation (0|1) + DEBUG = 1 + ``` + +* Adjust `pattern.lua` to your needs + + **The light pattern:** + + Depending on your preferences how to use stickers on real vinyl (some people use 1, some people use multiple markers), you can adjust the light pattern. + + ```lua + -- LED patern (list of LED positions to use) + -- + -- Format: + -- { {angle_offset=0, r=0, g=0, b=255}, {angle_offset=180, r=255, g=0, b=0} } + -- + -- Values of single item: + -- angle_offset (0..359): 0 = current position + -- r, g, b (0..255): color value for R, G and B + PATTERN = { + {angle_offset=0, r=0, g=0, b=255}, + {angle_offset=120, r=255, g=0, b=0}, + {angle_offset=240, r=255, g=255, b=255}, + } + ``` + + This example pattern uses 3 LEDs in parallel to mark 0°, 120° and 240° (like the Mercedes star): + * 0° (the actual position): bright blue + * 120°: bright red + * 240°: white + + + How to calculate the possible angles: + + In this exmple, we use a LED ring with 24 LEDs, which results in 15°/LED (360°/24=15°). LED positions start at 1 and angles are integers. + + | LED position | Angle range | + |:-------------:|:------------:| + | 1 | 0..14° | + | 2 | 15..29° | + | 3 | 30..44° | + | .. | .. | + | 24 | 345..359° | + + +* Upload all `*.lua` files to the ESP + + e.g. with [ESPlorer - IDE for ESP development](https://esp8266.ru/esplorer/) + +* Reboot + + +## Concept + +The ESP will listen to and execute RPC commands directly from serial port (UART 0). + +The main method is to set the rotation angle and control the LEDs accordingly to visualize this rotation angle. + +To trigger it, send the following string with the `angle` as an integer of the current rotation (in degree from 0..359): +```lua +r(angle)\r\n +``` +_This is exactly what the SC will send via UART3(J7) later._ diff --git a/mods/led_ring/software/config.lua b/mods/led_ring/software/config.lua new file mode 100644 index 0000000..ed7f575 --- /dev/null +++ b/mods/led_ring/software/config.lua @@ -0,0 +1,18 @@ +-- LED ring (ws2812) -------------------------- + +-- Number of LEDs +LED_COUNT = 24 + +-- 3 for RGB strips and 4 for RGBW strips +BYTES_PER_LED = 3 + + + +-- Debug mode --------------------------------- + +-- Enable demo signal to show a hard coded LED rotation (0|1) +DEBUG = 0 + + + +-- Hint: See pattern.lua to configure the LED pattern diff --git a/mods/led_ring/software/init.lua b/mods/led_ring/software/init.lua new file mode 100644 index 0000000..5d9da21 --- /dev/null +++ b/mods/led_ring/software/init.lua @@ -0,0 +1,26 @@ +local boot_delay = 5 -- in sec; allows recovery when script goes crazy + +function init_real() + tmr.stop(0) + dofile("config.lua") + dofile("pattern.lua") + + -- Init ws2812 LEDs + print("[INIT] WS2812 ("..LED_COUNT.." LEDs) ..") + ws2812.init() + led_buffer = ws2812.newBuffer(LED_COUNT, BYTES_PER_LED) + led_buffer:fill(0, 0, 5) -- all LEDs soft blue to show it's initialized + ws2812.write(led_buffer) + dofile("led.lua") + + -- Init serial port to receive RPC calls + local uart_id = 0 -- only UART 0 is capable of receiving data + local echo = 1 + uart.setup(uart_id, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, echo) + print ("[UART] Config", uart.getconfig(uart_id)) + + wifi.setmode(wifi.NULLMODE) +end + +tmr.alarm(0, boot_delay*1000, 0, function() init_real() end) +print("Boot delay ("..boot_delay.."s) ..") diff --git a/mods/led_ring/software/led.lua b/mods/led_ring/software/led.lua new file mode 100644 index 0000000..b9a2771 --- /dev/null +++ b/mods/led_ring/software/led.lua @@ -0,0 +1,27 @@ +led_buffer:fill(0, 0, 0); +local degree_per_led = 360 / LED_COUNT + +function _angle_to_led_pos(angle) -- returns index of LED (1..LED_COUNT) by angle in degree + angle = angle + math.ceil( -angle / 360 ) * 360 -- normalize angle to 0..359 + pos = math.ceil((angle+1) / degree_per_led) + return pos +end + +function r(angle) + -- Set new rotation position (angle= 0..360°). + -- Triggered via direct RPC from serial port. + led_buffer:fill(0, 0, 0); + for i = 1, #PATTERN do + led_pos = _angle_to_led_pos(angle + PATTERN[i].angle_offset) + led_buffer:set(led_pos, PATTERN[i].g, PATTERN[i].r, PATTERN[i].b) + end + ws2812.write(led_buffer) +end + + +if DEBUG == 1 then + print "[DEBUG] Demo mode with fake rotation signal." + local debug_tmr = tmr.create(); local debug_angle = 0; local debug_angle_step = 5 + debug_tmr:register(20, tmr.ALARM_AUTO, function (t) debug_angle = debug_angle + debug_angle_step; debug_angle = debug_angle + math.ceil( -debug_angle / 360 ) * 360; r(debug_angle) end) + debug_tmr:start() +end diff --git a/mods/led_ring/software/pattern.lua b/mods/led_ring/software/pattern.lua new file mode 100644 index 0000000..44c8d83 --- /dev/null +++ b/mods/led_ring/software/pattern.lua @@ -0,0 +1,13 @@ +-- LED patern (list of LED positions to use) +-- +-- Format: +-- { {angle_offset=0, r=0, g=0, b=254}, {angle_offset=180, r=254, g=0, b=0} } +-- +-- Values of single item: +-- angle_offset (0..359): 0 = current position +-- r, g, b (0..255): color value for R, G and B +PATTERN = { + {angle_offset=0, r=0, g=0, b=255}, + {angle_offset=120, r=255, g=0, b=0}, + {angle_offset=240, r=255, g=255, b=255}, +} diff --git a/software/DEVELOPMENT.md b/software/DEVELOPMENT.md new file mode 100644 index 0000000..fb78b7e --- /dev/null +++ b/software/DEVELOPMENT.md @@ -0,0 +1,81 @@ +# Development setup + +_DISCLAIMER: This developer help was written with very limited beginner knowledge in all these topics. Take it with caution!_ +_I figured out all this by try and error and i'm sure there are better ways of doing it. Still hope this helps someone who wants to tinker around in the future. Corrections appreciated. – @psturm_ + + +## install buildroot env + +As preparation, create ARM buildroot to be able to compile for the SC.. + +```sh +# download and unpack +wget https://buildroot.org/downloads/buildroot-2018.08.4.tar.gz +mv ./buildroot-2018.08.4.tar.gz /opt +cd /opt +tar xfv buildroot-2018.08.4.tar.gz + +# prepare config & overlay +cd +cp ./os/buildroot/buildroot_config /opt/buildroot-2018.08.4/.config +cp -R ./os/buildroot/sc1000overlay /opt/buildroot-2018.08.4/ + +# build +cd /opt/buildroot-2018.08.4/ +make # takes some time .. +``` + + +## build `xwax` + +Requires a buildroot environment (see setion above). + +To build the `xwax` binary from source: + +```sh +cd ./software + +# Adjust path in Makefile to your buildroot: +# CC=/opt/buildroot-2018.08.4/output/host/usr/bin/arm-linux-gcc + +make clean && make xwax +``` + +In my case, this still created wrong paths in the binary. As a quick fix, i created a symlink `/root/buildroot-2018.08.4 -> /opt/buildroot-2018.08.4` and used this in Makefile: `CC=/root/buildroot-2018.08.4/output/host/usr/bin/arm-linux-gcc` (there are better ways to do this for sure). + + +## debugging SC1000 + +Needs a USB-TTL-serial-converter to connect to UART of main processor on the SC1000. + +Check "6.1.1 UART1 interface" in https://www.olimex.com/Products/SOM/A13/A13-SOM-512/resources/A13-SOM-um.pdf (page 24) + +Hint: don't forget to cross RX & TX! + +To connect: +`screen /dev/ttyUSB0 115200` (Adjust the USB port to your actual one) + +or maybe use `GtkTerm` + + +## DeviceTreeBlob (dtb) + +To change hardware mappings (e.g. PIN layouts) + +```sh +cd ./updater/tarball/ + +# binary -> source +dtc -I dtb -O dts sun5i-a13-olinuxino.dtb > sun5i-a13-olinuxino.dts + +# Change the source file to your needs + +# source -> binary +dtc -O dtb -o sun5i-a13-olinuxino.dtb -b 0 sun5i-a13-olinuxino.dts +``` + + + +Customized DTS for the LED Mod: +* Remove power LED on PG9 +* Enable uart3 (RX:PG9, TX:PG10), results in `/dev/ttyS1` on SC1000 (see `led_mod.c`) diff --git a/software/Makefile b/software/Makefile index f9b7079..31ee7fb 100644 --- a/software/Makefile +++ b/software/Makefile @@ -51,6 +51,7 @@ OBJS = controller.o \ device.o \ dummy.o \ external.o \ + led_mod.o \ player.o \ realtime.o \ rig.o \ diff --git a/software/README b/software/README index c8497e2..64d6faa 100644 --- a/software/README +++ b/software/README @@ -1,4 +1,4 @@ SC1000 Xwax - xwax butchered to work with the SC1000 digital scratch instrument - +See DEVELOPMENT.md for hints for local development. diff --git a/software/led_mod.c b/software/led_mod.c new file mode 100644 index 0000000..708d2fe --- /dev/null +++ b/software/led_mod.c @@ -0,0 +1,119 @@ +// Optional LED mod +// Thread that reads the rotation angle of the plater and writes a RPC call to serial port (UART3) + +#include +#include +#include +#include +#include +#include +#include "player.h" +#include "xwax.h" + + +// file descriptor for UART3 serial port +int uart3_fd; + + + +void LED_Mod_init() +{ + printf("\nInitializing LED mod ..\n"); + + // find the TTY name of uart3 + FILE *fp; + char serial3_name[32]; + // 0x1c28c00 is the UART3/PG9 (see DTB/DTS file) + fp = popen("dmesg | grep \"0x1c28c00\" | grep -Eow \"ttyS[0-9]+\"", "r"); + if (fp == NULL) { + printf("[LED mod] Failed to determine uart3 tty name.\n"); + exit(1); + } + fgets(serial3_name, sizeof(serial3_name), fp); + pclose(fp); + serial3_name[strcspn(serial3_name, "\n")] = 0; // trim newline + char serial3_name_full[48] = "/dev/"; + strncat(serial3_name_full, serial3_name, sizeof(serial3_name)); + + // Initialize UART3 (for LED mod) + printf("Connecting LED mod to serial interface: %s\n", serial3_name_full); + uart3_fd = open(serial3_name_full, O_RDWR); + if (uart3_fd < 0) { + printf("[LED mod] Error %i from open: %s\n", errno, strerror(errno)); + exit(errno); + } + struct termios tty_ledmod; + if (tcgetattr(uart3_fd, &tty_ledmod) != 0) { + printf("[LED mod] Error %i from tcgetattr: %s\n", errno, strerror(errno)); + exit(errno); + } + + // https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/#basic-setup-in-c + + tty_ledmod.c_cflag &= ~PARENB; // Clear parity bit, disabling parity + tty_ledmod.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication + tty_ledmod.c_cflag |= CS8; // 8 bits per byte + + // output config + tty_ledmod.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) + tty_ledmod.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed + + // Set in/out baud rate to be 115200 + cfsetispeed(&tty_ledmod, B115200); + cfsetospeed(&tty_ledmod, B115200); + + // Save tty settings, also checking for error + if (tcsetattr(uart3_fd, TCSANOW, &tty_ledmod) != 0) { + printf("[LED mod] Error %i from tcsetattr: %s\n", errno, strerror(errno)); + exit(errno); + } +} + + +void *LED_Mod_InputThread_Simple(void *ptr) +{ + LED_Mod_init(); + + struct timespec ts_sleep; + int msec = 20; + ts_sleep.tv_sec = 0; + ts_sleep.tv_nsec = (msec % 1000) * 1000000; + + const int rot_msg_max_size = 10; + char rot_msg[rot_msg_max_size]; + + int rotation_angle; + int size; + + while (1) { + rotation_angle = (int)player_get_position_angle(&deck[1].player); + size = snprintf(rot_msg, rot_msg_max_size, "r(%d)\r\n", rotation_angle); + //printf("\nWriting rotation to serial: %s\n", rot_msg); + + /* The format of the output is a RPC in the format: r(120)\r\n + * + * The receiving side interprets this as direct call to it's r() method, + * passing the angle in degrees as integer. + */ + write(uart3_fd, rot_msg, size); + + tcdrain(uart3_fd); + nanosleep(&ts_sleep, NULL); + } +} + + +// Start the thread for the LED mod +void LED_Mod_Start() +{ + pthread_t thread1; + const char *message1 = "Thread LED mod"; + int iret1; + + iret1 = pthread_create(&thread1, NULL, LED_Mod_InputThread_Simple, (void *)message1); + if (iret1) { + fprintf(stderr, "Error - pthread_create() for LED mod return code: %d\n", iret1); + exit(EXIT_FAILURE); + } +} + diff --git a/software/led_mod.h b/software/led_mod.h new file mode 100644 index 0000000..a52511d --- /dev/null +++ b/software/led_mod.h @@ -0,0 +1,6 @@ +#ifndef SC_INPUT_H +#define SC_INPUT_H + +void LED_Mod_Start(); + +#endif diff --git a/software/player.c b/software/player.c index bd3e8f2..bc23ea0 100644 --- a/software/player.c +++ b/software/player.c @@ -311,6 +311,20 @@ double player_get_position(struct player *pl) return pl->position; } +/* Returns the rotation angle as integer (0..359). + * + * This is a helper method for the optinonal LED ring mod. + */ +double player_get_position_angle(struct player *pl) +{ + double rotations_per_second = (double)scsettings.platterspeed / 4096; + + double rotations = pl->position * rotations_per_second; + double rotation_relative = rotations - trunc(rotations); + + return rotation_relative * 360; +} + double player_get_elapsed(struct player *pl) { return pl->position - pl->offset; diff --git a/software/player.h b/software/player.h index 93f29c6..4f567ae 100644 --- a/software/player.h +++ b/software/player.h @@ -98,6 +98,7 @@ void player_set_track(struct player *pl, struct track *track); void player_clone(struct player *pl, const struct player *from); double player_get_position(struct player *pl); +double player_get_position_angle(struct player *pl); double player_get_elapsed(struct player *pl); double player_get_remain(struct player *pl); bool player_is_active(const struct player *pl); diff --git a/software/sc_input.c b/software/sc_input.c index e97046c..4c5f8d7 100644 --- a/software/sc_input.c +++ b/software/sc_input.c @@ -25,6 +25,7 @@ #include "rig.h" #include "track.h" #include "xwax.h" +#include "led_mod.h" #include "sc_input.h" #include "sc_midimap.h" #include "dicer.h" @@ -57,7 +58,7 @@ void i2c_read_address(int file_i2c, unsigned char address, unsigned char *result *result = address; if (write(file_i2c, result, 1) != 1) { - printf("I2C read error\n"); + printf("I2C write error\n"); exit(1); } @@ -1060,6 +1061,15 @@ void *SC_InputThread(void *ptr) int secondCount = 0; + if (scsettings.ledringenabled) + { + // Enable optional LED mod + printf("LED ring mod enabled.\n"); + LED_Mod_Start(); + } else { + printf("LED ring mod disabled.\n"); + } + while (1) // Main input loop { diff --git a/software/scsettings.txt b/software/scsettings.txt index 07240ac..d9fe158 100644 --- a/software/scsettings.txt +++ b/software/scsettings.txt @@ -207,3 +207,14 @@ mididelay=5 # Fader is assigned to sample pitch #midii=11,0,0,CH1_PITCH + + + +###################### +# LED mod (optional) # +###################### +# +# See ../mods/led_ring/README.md + +# 1 to enable LED ring mod, default 0 (disabled) +#ledringenabled=1 diff --git a/software/xwax.c b/software/xwax.c index ff5ad03..8346b9d 100644 --- a/software/xwax.c +++ b/software/xwax.c @@ -47,6 +47,7 @@ #include "sc_input.h" #include "sc_midimap.h" #include "dicer.h" +#include "led_mod.h" #define DEFAULT_IMPORTER EXECDIR "/xwax-import" @@ -115,6 +116,8 @@ void loadSettings() scsettings.disablevolumeadc = 0; scsettings.disablepicbuttons = 0; + scsettings.ledringenabled = 0; + // Load any settings from config file fp = fopen("/media/sda/scsettings.txt", "r"); if (fp == NULL) @@ -161,6 +164,8 @@ void loadSettings() scsettings.pitchrange = atoi(value); else if (strcmp(param, "jogreverse") == 0) scsettings.jogReverse = atoi(value); + else if (strcmp(param, "ledringenabled") == 0) + scsettings.ledringenabled = atoi(value); else if (strstr(param, "midii") != NULL) { scsettings.midiRemapped = 1; diff --git a/software/xwax.h b/software/xwax.h index 99f966f..0f91993 100644 --- a/software/xwax.h +++ b/software/xwax.h @@ -92,6 +92,13 @@ typedef struct SC_SETTINGS { bool midiRemapped; bool ioRemapped; + /* Optional mods */ + + // Enable the LED ring mod (send rotation angle to UART3) + // 1 when enabled, 0 when not (default: 0) + int ledringenabled; + + } SC_SETTINGS; extern SC_SETTINGS scsettings; diff --git a/updater/README.md b/updater/README.md new file mode 100644 index 0000000..5e72857 --- /dev/null +++ b/updater/README.md @@ -0,0 +1,39 @@ +# Update SC1000 + +Besides just updating the `xwax` version, there's also a full firmware upgrade process. + +> SC1000 v1.3 firmware update! (2020-06-02) +> https://www.youtube.com/watch?v=4zC_MFa_150 + + +1. Download the firmware: http://rasteri.com/SC1000_V1.3.zip (might be outdated, when you read this). + + Or build yourself, see [../software/DEVELOPMENT.md](./../software/DEVELOPMENT.md). + +2. Unpack the zip file in the root of the USB stick. + + Zip file contains: + * `sc.tar` + - some `*.mp3` files: for audio feedback during the update process + - `sun5i-a13-olinuxino.dtb`: DeviceTreeBlob to change hardware config + - `xwax`: the actual updated `xwax` software + - `zImage`: compressed version of the linux kernel image + * `scsettings.txt` + * `xwax` replacement script (which triggers update, then calls actual `xwax`) + +3. Install on SC + + Boot your SC1000 while holding down any (or both) of the beat selection buttons. Make sure you use headphones, because the result of the upgrade will be output via audio. + +5. Reboot + + You might need to remove the `xwax` replacement script from the USB stick + + To _hear_ the firmware version: hold down sample select up during boot + + +## Build new firmware version + +#### Create new `os-version.mp3` + +e.g. use https://ttsmp3.com/ diff --git a/updater/sc.tar b/updater/sc.tar index e5e34f3..39769ee 100644 Binary files a/updater/sc.tar and b/updater/sc.tar differ diff --git a/updater/tarball/os-version.mp3 b/updater/tarball/os-version.mp3 index 26c89bd..7bd0dbd 100644 Binary files a/updater/tarball/os-version.mp3 and b/updater/tarball/os-version.mp3 differ diff --git a/updater/tarball/sun5i-a13-olinuxino.dtb b/updater/tarball/sun5i-a13-olinuxino.dtb index 1030a1a..6821192 100644 Binary files a/updater/tarball/sun5i-a13-olinuxino.dtb and b/updater/tarball/sun5i-a13-olinuxino.dtb differ diff --git a/updater/tarball/xwax b/updater/tarball/xwax index 5708b40..0245f18 100755 Binary files a/updater/tarball/xwax and b/updater/tarball/xwax differ