There is currently an issue with the latest version of raspberry OS and i2s audio. If you wish to use i2s audio please stay with this version of raspberry os https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2023-12-06/
SocketMost for use with PiMost
PiMost header info https://github.com/rhysmorgan134/SocketMost/wiki/PiMost
This is a library for use with the PiMost to allow Most Bus messages (Most 25 only) to be sent to various applications. This package just gives out a json formatted string over a unix Datagram socket that can then be consumed through which ever application you wish. The implementation is currently at a very early stage, and has been tested on a Jaguar and Land rover system running at 48khz. In theory 44.1khz should be useable but will need some configuration changes around the registers (as a hint look into legacy start up mode, and only using the RX from the transceiver as the locking source) this is untested and no guarantee it will work in the way highlighted below.
First clone this repo
git clone https://github.com/rhysmorgan134/SocketMost.git
cd SocketMost
If you don't have NodeJS installed you can use the help script to install it
chmod +x install_nodejs.sh
./install_nodejs.sh
To use the library it needs to be built
npm install
npm run build
The audio drivers have been modified from this super useful overlay. The piMost needs i2s audio, and luckily the clocking source is provided by the MOST network, so rather than having to deal with the awful Pi audio clocks, we get a great clean signal.
#change to the overlays directory
cd dtoverlays
#If using a pi4
cd pi
#Otherwise if using a pi5
cd pi5
#build the overlay
dtc -@ -H epapr -O dtb -o piMost48KhzStereo.dtbo -Wno-unit_address_vs_reg piMost48KhzStereo.dts
#copy the built overlay
sudo cp piMost48KhzStereo.dtbo /boot/overlays
#edit pulse audio config to default all audio the 48khz
sudo nano /etc/pulse/daemon.conf
#uncomment/edit the file to have the below
default-sample-format = s16le
default-sample-rate = 48000
alternate-sample-rate = 48000
default-sample-channels = 2
default-channel-map = front-left,front-right
If you wish to make use of the PiMost Canbus channel, then follow the below
sudo apt update
sudo apt install can-utils
Then follow the optional steps in Boot Config section below
If the shutdown jumper is not in place, then after MOST network activity stops, power will be cut from the supply after ~30seconds. The idea of this is that when MOST activity stops, we pick this up via GPIO, and after a configurable delay the Pi gets shutdown gracefully then after 30 seconds of the last activity power then gets completely cut, lowering the consumption to around 0.5ma. This works with both the USB-C power PiMost and also the 12v supply PiMost. Follow the relevant part of the Boot config section to enable this.
Now we can set up the boot config options
#bookworm
sudo nano /boot/firmware/config.txt
#pre bookworm
sudo nano /boot/config
Uncomment these two lines:
dtparam=i2s=on
dtparam=spi=on
At the bottom of the file add:
dtoverlay=piMost48KhzStereo
If you are using the canbus channel, also add
dtoverlay=mcp2515-can1,oscillator=16000000,interrupt=25
To enable auto shutdown we need to add the below line, the debounce value (milliseconds) allows a configurable delay before issuing an OS shutdown this can be changed by preference, but needs to less than 30 seconds to allow a graceful shutdown before power is removed by the PiMost.
dtoverlay=gpio-shutdown,gpio_pin=26,active_low=0,debounce=2000
sudo raspi-config
advanced settings > audio >
#Reboot the pi
arecord -l
#Take not of the card and device number. !!!
sudo nano /etc/pulse/default.pa
#add the below to the end of the file replace the c and d with you card and device number from above
load-module module-alsa-source device=hw:c,d
.ifexists module-udev-detect.so
reboot once again
Change into the root directory then run
npm run build
followed by
cd examples
LOG_LEVEL=denug node server.js
You should see a bunch of messages out on the console. An example of a healthy start up is below
pi@raspberrypi:~/SocketMost/examples $ LOG_LEVEL=debug node server.js
info: config file exists: {"version":"1.0.0","nodeAddress":366,"groupAddress":34,"freq":48,"mostExplorer":true} SocketMost
info: creating driver nodeAddress 0x16e groupAddress: 0x22 freq: 48 SocketMost
info: GPIO config: {"interrupt":404,"fault":405,"status":415,"mostStatus":425,"reset":416} OS8104 Driver
info: starting up OS8104 Driver
info: resetting OS8104 Driver
debug: writing reset OS8104 Driver
debug: waiting reset OS8104 Driver
info: most explorer enabled, starting server.... SocketMost
Listening for Most-Explorer requests on 0.0.0.0:5555
fault 1
debug: stopping reset OS8104 Driver
info: initial reset complete carrying out init OS8104 Driver
debug: removing all interrupts OS8104 Driver
info: running config OS8104 Driver
addressLow: 0x6e addressHigh: 0x1 groupAddress: 0x22
debug: writing registry: 8a with value: 1 OS8104 Driver
debug: writing registry: 8b with value: 6e OS8104 Driver
debug: writing registry: 89 with value: 22 OS8104 Driver
debug: writing registry: 83 with value: 0 OS8104 Driver
debug: writing registry: 8d with value: 3 OS8104 Driver
debug: writing registry: 92 with value: 2 OS8104 Driver
debug: writing registry: 80 with value: 0 OS8104 Driver
debug: writing registry: 82 with value: d3 OS8104 Driver
debug: writing registry: 8c with value: 40 OS8104 Driver
debug: writing registry: 81 with value: 50 OS8104 Driver
debug: writing registry: 88 with value: 7 OS8104 Driver
debug: writing registry: 85 with value: f OS8104 Driver
warn: most error active OS8104 Driver
Error 1 91
error: parsing fault mask: 5b OS8104 Driver
error: Error: transceiver lock error OS8104 Driver
warn: transceiver unlocked OS8104 Driver
fault 0
debug: checking for lock OS8104 Driver
debug: lock status: 0x42 OS8104 Driver
debug: pllLocked: 0 OS8104 Driver
debug: Lock Source: 0 OS8104 Driver
warn: locked OS8104 Driver
debug: message received OS8104 Driver
debug: MOST message parsed: {"type":0,"sourceAddrHigh":1,"sourceAddrLow":128,"fBlockID":49,"instanceID":2,"fktID":1043,"opType":12,"telID":1,"telLen":12,"data":{"type":"Buffer","data":[0,4,0,1,0,1,1,0,1,0,21,0]}} OS8104 Driver
debug: message received OS8104 Driver
debug: MOST message parsed: {"type":0,"sourceAddrHigh":1,"sourceAddrLow":128,"fBlockID":49,"instanceID":2,"fktID":3124,"opType":12,"telID":1,"telLen":12,"data":{"type":"Buffer","data":[0,0,1,0,0,21,0,1,0,1,1,0]}} OS8104 Driver
debug: message received OS8104 Driver
debug: MOST message parsed: {"type":0,"sourceAddrHigh":1,"sourceAddrLow":128,"fBlockID":49,"instanceID":2,"fktID":3124,"opType":12,"telID":3,"telLen":8,"data":{"type":"Buffer","data":[2,0,0,0,0,1,1,0,0,0,0,0]}} OS8104 Driver
debug: message received OS8104 Driver
debug: MOST message parsed: {"type":0,"sourceAddrHigh":1,"sourceAddrLow":128,"fBlockID":49,"instanceID":2,"fktID":514,"opType":12,"telID":0,"telLen":2,"data":{"type":"Buffer","data":[0,1,0,0,0,0,0,0,0,0,0,0]}} OS8104 Driver
debug: message received OS8104 Driver
debug: MOST message parsed: {"type":0,"sourceAddrHigh":1,"sourceAddrLow":128,"fBlockID":49,"instanceID":2,"fktID":1042,"opType":12,"telID":0,"telLen":1,"data":{"type":"Buffer","data":[3,0,0,0,0,0,0,0,0,0,0,0]}} OS8104 Driver
Open a terminal in the socketmost root directory, run
git pull
Followed by
npm run build
The latest version will then run when you launch server.js
There are various minimum log levels supported through the use of winston, default is info
LOG_LEVEL=silly
LOG_LEVEL=debug
LOG_LEVEL=info
LOG_LEVEL=warn
LOG_LEVEL=error
If you are still in the dtoverlay folder, change up two directories
cd ../..
Get the current directory
pwd
If you have installed as the standard pi user the path should look like the below, if you have a custom user, then it should be the same besides the user pi
/home/pi/SocketMost/examples/server.js
Take note of this, and then create a systemd file
sudo nano /etc/systemd/system/socketmost.service
Paste the below code into the file, if needed change line that begins with ExecStart and working directory to match your path from above, if the user is not pi then also change that value to match your username.
[Unit]
Description=socketmost
After=network.target
[Service]
ExecStart=node /home/pi/SocketMost/examples/server.js
Restart=always
WorkingDirectory=/home/pi/SocketMost/examples
User=pi
[Install]
WantedBy=default.target
Press Cntrl X
followed by Cntrl Y
to save the file
Now enable to service
systemctl enable socketmost.service
now reboot the pi
sudo reboot now
I have created a visual tool to help with exploring the Most Bus. Binaries can be downloaded from here:
https://github.com/rhysmorgan134/most-explorer/releases
This can be run on a different computer to the pi (or the same if needed!) the first step is inside the socketmost/examples directory run
node server.js
Then on the computer that has most-explorer installed, launch the app, after a few seconds it should find the socketmost server and you should see messages coming in.
The SocketMost service can emit multiple events, and also receive events, data should be sent over to the unix socket from the client the client needs to be a datagram with a matching filename and location to below:
/tmp/SocketMost-client.sock
And connect to
"/tmp/SocketMost.sock"
The events that the PiMost emits all follow the same json structure
{
"eventType": 'event type is here',
"data": 'data that relates to the event goes here'
}
Possible events and their structures are below
{
"eventType": "newMessage",
"type": 1, //message type as received and specified in the most specification
"sourceAddrHigh": 1, //source address of the message high bye
"sourceAddrLow": 97, //source address of the message low bye
"data": { //data packet
"type": "Buffer", //inserted from the PiMost service to specify its a buffer
"data": [1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //The actual data buffer, values can be parsed out FBlock, Function etc as per the MOST spec
}
}
{
"eventType": "locked" //PiMost is locked onto the network and ready to send and receive messages
}
{
"eventType": "unlocked" //PiMost is not locked to the network and will not service message requests
}
{
"eventType": "positionUpdate" //PiMost is not locked to the network and will not service message requests
"nodePostion": 3 //Position relative to the master, Netblock Function block, must use the as the instance ID in the user application
"maxPositon": 5 //Max position of last node on the ring
}
{
"eventType": 'messageSent' //request to send message has been completed successfully, ready to send next
}
masterFound - important as MOST communication kicks off from the master, typical flow is master requests function blocks-> applic respond with implemented blocks
{
"eventType": "masterFound" //Network master has been identified
"instanceID": 1, //network master instance id
"sourceAddrHigh": 1 //network master source address high
"sourceAddrLow" 45 //network master source address low
}
{
"eventType": "allocResult",
"loc1": 4, //first byte that has been assigned to the PiMost and the first byte that PiMost Audio is inserted to
"loc2": 5, //second byte that has been assigned to the PiMost and the second byte that PiMost Audio is inserted to
"loc3": 6, //third byte that has been assigned to the PiMost and the third byte that PiMost Audio is inserted to
"loc4": 7, //fourth byte that has been assigned to the PiMost and the fourth byte that PiMost Audio is inserted to
"cl": 4, //connection label for the PiMost to de-allocate
"answer1": "ALLOC_GRANT", //Allocation response
"freeChannels": 20 //Amount of remaining free channels
}
The PiMost can also receive events in the same way, these are listed below, the format must match and be a json string sent over the UDP socket
{
"eventType": "sendControlMessage",
"targetAddressHigh": 1, //MOST node address high byte to send the message to
"targetAddressLow": 97, //MOST node address low byte to send the message to
"fBlockID": 1, //Most function block that the messsage relates to, Network Master is the example here
"instanceID": 0, //The instance ID of the above FBlock, network Master is always 0
"fktId": 0, //The function ID that the message relates to
"opType": 12, //OpType 12=status, full enumerations are in the MOST Book
"data": [] //The raw data to go with the message, the SocketMost service handles TelID, TelLength etc. Currently only single part sends are supported
}
{
"eventType": "getNodePosition" //SocketMost will emit positionUpdate with response
}
{
"eventType": "getMaster" //SocketMost will emit masterFound with response
}
{
"eventType": "allocate" //SocketMost will emit allocResult with reference to the PiMosts Streaming bytes
}