LanBox

From NURDspace
LanBox-LCX
LanBox-LCX.jpg
Owner User:zmatt
Status Infrastructure
Hostname lanbox
Tool
Tool category

LanBox-LCX

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
    • 36 MHz (18 MIPS)
    • 3 KB internal SRAM (cpu regs and stack are allocated here)
    • USB device port
    • high-speed UART, used for DMX in/out
    • SPI, connects to A/D converter (TLC1543C)
    • IOM-2 interface (not connected)
    • JTAG debug support
    • the usual bunch of timers and GPIO
    • external bus interface controller
  • Non-multiplexed bus (22-bit address + 16-bit data) connects to:
    • 1 MB SRAM (max 2 MB supported)
    • 1 MB flash (max 4 MB supported)
    • 10base-T ethernet controller (CS8900A)
    • UART (TL16C550C), used for MIDI in/out
    • digital outputs (74AHCT574)

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.)