GLM Capture 2.1 - Raspberry Pi Pico 2 firmware for reading the Genelec GLM RS-485 bus
=====================================================================================

Notice
------
This is not a product of Genelec Oy. It is a personal hobby project by Pasi Vähämartti.
More information: blog.vahamartti.fi

What it does
------------
The firmware listens to the GLM bus (RS-485, 296000 baud, 9 data bits, no parity, 2 stop
bits, 9N2) and sends every complete frame to the PC over USB as one line of text. It only
listens: nothing is ever sent to the bus. There is no display and no menu.

The Pico 2 does the work with both of its cores. A PIO state machine reads the 9N2 bits
(the Pico's UART cannot do 9 data bits). Core 1 only receives: it empties the PIO FIFO,
removes the HDLC escapes, assembles the frames and stores them with a time stamp and a
sequence number in a ring buffer. Core 0 formats the frames as text and sends them over USB.


Speeds at a glance
------------------
  GLM bus (RS-485):   296000 baud, 9N2. Fixed in the firmware; you do not set it anywhere.
  USB serial port:    921600 or any speed higher than the bus speed. The data goes over USB, so
                      the value has no real effect, but do not choose less than 296000.
                      The PuTTY settings are in "Reading the data".


What you need
-------------
- Raspberry Pi Pico 2 (RP2350).
- A TTL to RS-485 module with a 3.3 V capable transceiver, for example a MAX3485 module.
- A cable or connector for the GLM bus (the bus uses RJ-45 connectors, but it is not Ethernet).
- A USB cable and a Windows PC. No programming tools are needed.


Wiring
------
Receive only. The Pico reads one pin, GP1.

  RS-485 module            connect to
  ---------------------    --------------------------------------------
  VCC                      Pico 3V3 (3.3 V, not 5 V)
  GND (TTL side)           Pico GND
  TXD (receive output)     Pico GP1
  RXD (transmit input)     not connected
  D+ / A                   GLM bus RJ-45 pin 1 (A, D+)
  D- / B                   GLM bus RJ-45 pin 2 (B, D-)
  GND (RS-485 side)        not connected  (RJ-45 pin 8, the bus ground, is not connected)

Notes
- Power the module from 3.3 V. At 5 V the module's receive output would be a 5 V signal,
  which does not suit the Pico's GPIO pin.
- TXD and RXD are named from the microcontroller's point of view: TXD is the data coming out
  of the module, RXD is its transmit input. Leave RXD unconnected: connecting it to ground
  disturbed the bus in the original build (probably a ground loop).
- A termination at the receiver is not required; it is needed only in larger systems. In the
  original build the module is the last device on the line, so the 120 ohm termination is only
  at the transmitting end, and the setup works without problems in a ten-speaker system. Many
  modules have an optional built-in 120 ohm resistor (for example a solder jumper); leave it off
  unless you need it.
- The module does not have to be the last device on the line. To listen in the middle of the bus,
  add a second RJ-45 connector wired in parallel (the same pins on both connectors) so that the
  signals continue to the next device.
- Check the pin names printed on your own module before wiring. They differ between makers.


Putting the firmware on the Pico 2
-----------------------------------
The firmware is delivered as a ready-made UF2 file, glm_capture.UF2 (in this package).
No programming tools are needed.

1. Unplug the Pico 2 from the USB cable.
2. Hold down the BOOTSEL button on the Pico 2 and, while holding it, plug the USB cable
   into the PC. Release the button. The Pico appears on the PC as a USB drive named RP2350.
3. Copy glm_capture.UF2 onto that drive (drag and drop, or copy and paste).
4. The drive disappears and the Pico restarts by itself. The firmware is now installed.

After this the Pico shows up as a serial port (a COM port on Windows) every time it is
plugged in. To update the firmware later, repeat the steps above with the new file.

The firmware is for the Raspberry Pi Pico 2 (RP2350) only. It does not run on the original
Raspberry Pi Pico (RP2040).


Reading the data
----------------
Any terminal program that can open a serial port works, for example PuTTY.

PuTTY settings
  Connection type: Serial
  Serial line:     the Pico's COM port (see Windows Device Manager, "Ports (COM & LPT)")
  Speed:           921600 (any speed higher than 296000)
  Connection > Serial: Data bits 8, Stop bits 1, Parity None, Flow control None

Flow control must be None. PuTTY then turns the DTR line on, and the firmware only collects
frames while the USB port is open (DTR high). With any other flow control setting the screen
stays empty.

To save the data, choose Session > Logging > "All session output" and give a log file name,
for example glm_&Y&M&D_&T.txt (the date and time are added to the name).

Only one program can have the serial port open at a time.

Note: the computer and the Genelec GLM application must be running. Without them the bus
carries only the volume information (from the hub, for example when you turn the volume knob
or use the remote control). The other traffic, such as the polling and the replies from the
speakers, appears only while the GLM software is running and talking to the system.


Output format
-------------
One text line per item, CR/LF terminated.

  # glm-capture fw=2.1 baud=296000 fmt=9N2 t=<us>
      Sent once when the port is opened.

  @<us>,<seq> <addr> <cmd> <data...> <crc hi> <crc lo> 07E
      One frame with the HDLC escapes removed.
        <us>   time of the closing 07E in microseconds since the Pico was started
        <seq>  sequence number of the frame; a gap means that frames were lost
      Words are three hexadecimal digits: the first (9 bit) word is the address (1xx),
      the last is the end flag 07E. Example:
        @12345678,89 101 009 05D 0E7 07E

  # stat t=<us> seq=<n> drop=<n> ovf=<n> stall=<n> esc=<n> long=<n> trunc=<n> stray=<n>
      Loss and error counters, every second when something has changed, otherwise every 5 s.
        drop   frames lost because the USB queue was full
        ovf    words lost because the word ring was full
        stall  PIO FIFO overruns
        esc    frames discarded: invalid HDLC escape
        long   frames discarded: longer than 255 bytes
        trunc  frames abandoned: a new address word arrived before 07E
        stray  words received outside a frame (ignored)

The CRC is not checked in the firmware. It is CRC-16/GSM over the address low byte and the
payload; the last two data words before 07E are the CRC.


Status LED
----------
The on-board LED flashes briefly for every frame received. A slow blink means that no
frames have been seen for three seconds: check the wiring, the A/B polarity and that the
GLM system is on.


If nothing appears
------------------
- No lines at all: check the COM port number and that Flow control is None.
- Only "# glm-capture" and "# stat" lines, but no frames: the bus is not reaching the Pico.
  Check the A and B wires (try swapping them), the 3.3 V supply of the module and that the
  Pico's GP1 is connected to the module's TXD pin.
- Frames with a gap in the sequence number or growing "drop" counters: the PC or the USB
  connection is not keeping up. Use a USB port directly on the PC.


Version
-------
Firmware 2.1. The data format is unchanged; any program that reads the lines above works
with it.
