LanBox-LCX | |
---|---|
Owner | User:zmatt |
Status | Infrastructure |
Hostname | lanbox |
Tool | |
Tool category |
LanBox-LCX.jpg {{{InventoryOwner}}}Property "Tool Owner" (as page type) with input value "{{{InventoryOwner}}}" contains invalid characters or is incomplete and therefore can cause unexpected results during a query or annotation process. {{{Location}}}Property "Tool Location" (as page type) with input value "{{{Location}}}" contains invalid characters or is incomplete and therefore can cause unexpected results during a query or annotation process.
Description
This networked box controls the DMX lights which illuminate the space. The LanBox-LCX gets its commands from SpaceBot.
Applications
Features
The LanBox is typically controlled via a simple ascii protocol via TCP port 777 (max 5 connections), USB-serial, or MIDI-SysEx. If the last firmware upload was done via USB then it will consider that to be its console stream, otherwise it has a separate console on TCP port 778 (1 connection).
It also supports a variety of other MIDI messages and can broadcast/receive data via UDP. It supports up to 31 layers, each with an independent sequencer. Up to 3072 channels can be enabled across all layers combined, each with an independent fader. The layers are merged into the mixer buffer according to their configured mix-mode, and up to 512 channels can be output via DMX (freely selectable from the mixer buffer and with post-processing such as curve-mapping and slope-limiting).
DMX in and UDP in can be mapped to a layer or directly into the mixer. Some misc other stuff can optionally also be mapped into the mixer, such as its 8 analog inputs, clock (NTP), and MIDI timecode, and its 8 digital outputs can be controlled directly by mixer channels. The sequencers can set channels (with or without fade), control other layers, send arbitrary MIDI messages, bit-bang serial data over some or all of the digital outputs (independently), etc.
Internals (hardware)
- C165UTAH 16-bit cpu
- Non-multiplexed bus (22-bit address + 16-bit data) connects to:
Internals (software)
The firmware is based on a Forth system which you can enter by sending the command *b7#
on its console stream (see above). For symmetry, there's also a Forth word called *b7#
which gets you back into the normal command mode. Entering the Forth console does not affect other streams or normal operation (as long as you don't mess anything up).
There's a little script for logging into the lanbox Forth console in the lanbox-forth git repo.
The LanBox-LCX Forth system is a fairly complete native-compiling Forth system with integrated help (not very complete unfortunately), assembler, disassembler, debugger, etc. Although the processor is 16-bit with segmented addressing, the Forth system is 32-bit with flat addressing for convenience. Several key routines of the firmware are written in assembly for performance.
The firmware has several callback hooks (set to nop by default) to allow custom code to be run at various relevant moments:
' nop VALUE 'StartTick \ called in "start" after initialization, before the frame timer is started ' nop VALUE 'StopTick \ called in "stop" after frame timer has halted but before any cleanup ' nop VALUE 'PreMixTick \ called for every dmx frame before the sequence-fade-mix loop ' nop VALUE 'PostMixTick \ called after mixer buffer is updated but before postprocessing
It's also quite easy to patch dispatch tables to hook custom commands on e.g. MIDI messages.
With some care you can directly manipulate internal buffers and structures (e.g. in 'PostMixTick you can manipulate the updated mixer buffer before anything else gets to see it), and many serial commands also have an equivalent high-level Forth word, for example:
( 44 ) EnConfigure ( layerID destlayerID -- ok? ) ( 44 ) EnConfigureWithOptions ( layerID destlayerID newlayerID flags cuelist cuestep -- ok? ) ( 56 ) EnGo ( layerID cuelist cuestep -- ok? ) ( 57 ) EnClear ( layerID -- ok? ) ( 73 ) EnNextCue ( layerID -- ok? )
Patchwork
Style convention: bold green indicates command input, output prompt is blue, remaining output unstyled (except highlighting for emphasis).
Firmware has been upgraded to latest version. This has been done via TCP, hence the console is now available via TCP port 778. The first time you connect to it (after boot) you'll get the buffered startup message thrown at you. Use the LC command *b7# to switch to Forth mode: as usual for LC commands, this is not echoed back but acknowledged with a >.
LanBox-LCX system built Jun 26 2007 09:01:44 -------------------------------------------- *b7#>
Once in Forth mode, commands will be echoed. Press enter to see Forth's standard ok prompt:
*b7#> ok
The console is not aware of disconnect/connect and will remain in whatever state it was left in.
The bootloader settings have been changed to disable the CRC-verification of the firmware. This allows hassle-free customization of the firmware. This was done with the following Forth command:
mon" setsysparams 08 RAMsys 10000 210000 2A0000 *0 ok
If firmware is reuploaded via LCedit, this will need to be done again before doing any persistent code modification (using savecode), or the LanBox will refuse to boot due to CRC mismatch.
More UDP, less spam
Objective: allow the udp-transmit capability of the LanBox to be used (for efficiently getting the current state of the lanbox, including e.g. its analog inputs) without spamming the whole network with broadcasts.
The destination address for udp transmit turned out to be hardcoded to -1 (i.e. 255.255.255.255):
see udptxpacket UdpTxPacket 0884B8 DA 04 EA 1C 041CEA CALLS ROT 0884BC EC F3 R3 PUSH 0884BE EC F2 R2 PUSH 0884C0 98 20 R0 [+] R2 MOV 0884C2 98 30 R0 [+] R3 MOV 0884C4 DA 08 94 34 083494 CALLS UdpOutPort 0884C8 DA 04 8A 3E 043E8A CALLS -1 0884CC DA 08 5A 37 08375A CALLS UdpSock 0884D0 88 30 R3 R0 [-] MOV 0884D2 88 20 R2 R0 [-] MOV 0884D4 FC F2 R2 POP 0884D6 FC F3 R3 POP 0884D8 DA 08 94 30 083094 CALLS SOCK-UDP-WRITE 0884DC DA 04 C4 1B 041BC4 CALLS DROP 0884E0 DB 00 RETS ok
since calls use absolute addresses (with funny byteorder) this was easy to patch to use UdpInAddr instead (which is convenient for the purpose since it's already configurable via global settings). First, check its address:
' udpinaddr .hex 83590 ok
Patch the instruction (again look closely at byte order):
$359008DA $0884C8 ! ok
And finally check the results:
see udptxpacket ... 0884C4 DA 08 94 34 083494 CALLS UdpOutPort 0884C8 DA 08 90 35 083590 CALLS UdpInAddr 0884CC DA 08 5A 37 08375A CALLS UdpSock ... ok
w00t!
After thorough testing (read: it didn't crash, so I'm sure it'll work fine), it's time to save the work done:
Stop the application (in retrospect, maybe it would have been a better idea to do that before doing live code-patching), save code to flash, and reboot:
stop ok savecode ok reset \ (connection gone)
NOTE: Using savecode while the application is still running will fuck up the firmware. (TODO: add recovery procedure for fucked-up firmware.)