Merge branch 'main' into synthdexedpdate

pull/871/head
probonopd 2 months ago committed by GitHub
commit ecbae30c03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 67
      .github/workflows/build.yml
  2. 1
      src/Makefile
  3. 3
      src/Synth_Dexed.mk
  4. 88
      src/arm_float_to_q23.c
  5. 22
      src/arm_float_to_q23.h
  6. 2
      src/config.cpp
  7. 1
      src/mididevice.cpp
  8. 28
      src/minidexed.cpp
  9. 1
      src/minidexed.ini
  10. 6
      src/net/mdnspublisher.cpp
  11. 8
      submod.sh
  12. 57
      syslogserver.py

@ -1,9 +1,8 @@
# Build 32-bit and 64-bit separately
name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_INFO: ""
on:
push:
@ -19,14 +18,16 @@ jobs:
artifact-path: ${{ steps.upload64.outputs.artifact-path }}
steps:
- uses: actions/checkout@v2
- name: Compute Git Info for Artifact Name
run: echo "GIT_INFO=$(date +%Y-%m-%d)-$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Get specific commits of git submodules
run: sh -ex ./submod.sh
- name: Create sdcard directory
run: mkdir -p ./sdcard/
- name: Put git hash in startup message
run: |
sed -i "s/Loading.../$(date +%Y%m%d)-$(git rev-parse --short HEAD)/g" src/userinterface.cpp
sed -i "s/Loading.../${{ env.GIT_INFO }}/g" src/userinterface.cpp
# Install 64-bit toolchain (aarch64)
- name: Install 64-bit toolchain
run: |
@ -65,15 +66,30 @@ jobs:
cd -
cp -r ./circle-stdlib/libs/circle/boot/* sdcard
rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux
cp ./src/config.txt ./src/minidexed.ini ./src/*img ./src/performance.ini sdcard/
cp ./src/config.txt ./src/minidexed.ini ./src/performance.ini sdcard/
cp ./getsysex.sh sdcard/
echo "usbspeed=full" > sdcard/cmdline.txt
# Performances
git clone https://github.com/Banana71/Soundplantage --depth 1 # depth 1 means only the latest commit
cp -r ./Soundplantage/performance ./Soundplantage/*.pdf ./sdcard/
# Hardware configuration
cd hwconfig
sh -ex ./customize.sh
cd -
mkdir -p ./sdcard/hardware/
cp -r ./hwconfig/minidexed_* ./sdcard/minidexed.ini ./sdcard/hardware/
# WLAN firmware
mkdir -p sdcard/firmware
cp circle-stdlib/libs/circle/addon/wlan/sample/hello_wlan/wpa_supplicant.conf sdcard/
cd sdcard/firmware
make -f ../../circle-stdlib/libs/circle/addon/wlan/firmware/Makefile
cd -
- name: Upload 64-bit artifacts
id: upload64
uses: actions/upload-artifact@v4
with:
name: build64-artifacts
name: MiniDexed_${{ github.run_number }}_${{ env.GIT_INFO }}_64bit
path: sdcard/*
build32:
@ -83,14 +99,16 @@ jobs:
artifact-path: ${{ steps.upload32.outputs.artifact-path }}
steps:
- uses: actions/checkout@v2
- name: Compute Git Info for Artifact Name
run: echo "GIT_INFO=$(date +%Y-%m-%d)-$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Get specific commits of git submodules
run: sh -ex ./submod.sh
- name: Create sdcard directory
run: mkdir -p ./sdcard/
- name: Put git hash in startup message
run: |
sed -i "s/Loading.../$(date +%Y%m%d)-$(git rev-parse --short HEAD)/g" src/userinterface.cpp
sed -i "s/Loading.../${{ env.GIT_INFO }}/g" src/userinterface.cpp
# Install 32-bit toolchain (arm-none-eabi)
- name: Install 32-bit toolchain
run: |
@ -116,7 +134,7 @@ jobs:
id: upload32
uses: actions/upload-artifact@v4
with:
name: build32-artifacts
name: MiniDexed_${{ github.run_number }}_${{ env.GIT_INFO }}_32bit
path: sdcard/*
combine:
@ -124,32 +142,23 @@ jobs:
runs-on: ubuntu-22.04
needs: [ build64, build32 ]
steps:
- name: Download 64-bit artifacts
uses: actions/download-artifact@v4
with:
name: build64-artifacts
path: combined
- name: Download 32-bit artifacts
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: build32-artifacts
pattern: MiniDexed_*
merge-multiple: true
path: combined
- name: Create combined ZIP file
run: |
cd combined
zip -r ../MiniDexed_${GITHUB_RUN_NUMBER}_$(date +%Y-%m-%d)-$(git rev-parse --short HEAD).zip .
zip -r ../MiniDexed_${{ github.run_number }}_${{ env.GIT_INFO }}.zip .
cd ..
- name: Upload combined ZIP artifact
uses: actions/upload-artifact@v4
with:
name: combined-artifact
path: MiniDexed_${GITHUB_RUN_NUMBER}_$(date +%Y-%m-%d)-$(git rev-parse --short HEAD).zip
- name: Upload to GitHub Releases (only when building from main branch)
if: ${{ github.ref == 'refs/heads/main' }}
run: |
set -ex
export UPLOADTOOL_ISPRERELEASE=true
export UPLOADTOOL_PR_BODY="This is a continuous build. Feedback is appreciated."
export UPLOADTOOL_BODY="This is a continuous build. Feedback is appreciated."
wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
bash ./upload.sh ./MiniDexed*.zip
set -ex
export UPLOADTOOL_ISPRERELEASE=true
export UPLOADTOOL_PR_BODY="This is a continuous build. Feedback is appreciated."
export UPLOADTOOL_BODY="This is a continuous build. Feedback is appreciated."
wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
bash ./upload.sh ./MiniDexed*.zip

@ -10,6 +10,7 @@ OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \
mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \
sysexfileloader.o performanceconfig.o perftimer.o \
effect_compressor.o effect_platervbstereo.o uibuttons.o midipin.o \
arm_float_to_q23.o \
net/ftpdaemon.o net/ftpworker.o net/applemidi.o net/udpmidi.o net/mdnspublisher.o udpmididevice.o
OPTIMIZE = -O3

@ -40,8 +40,9 @@ INCLUDE += -I $(CMSIS_DSP_COMPUTELIB_INCLUDE_DIR)
DEFINE += -DUSE_FX
ifeq ($(strip $(AARCH)),64)
ifeq ($(RPI), $(filter $(RPI), 3 4 5))
DEFINE += -DARM_MATH_NEON
DEFINE += -DARM_MATH_NEON_EXPERIMENTAL
DEFINE += -DHAVE_NEON
endif

@ -0,0 +1,88 @@
#include "arm_float_to_q23.h"
#if defined(ARM_MATH_NEON_EXPERIMENTAL)
void arm_float_to_q23(const float32_t * pSrc, q23_t * pDst, uint32_t blockSize)
{
const float32_t *pIn = pSrc; /* Src pointer */
uint32_t blkCnt; /* loop counter */
float32x4_t inV;
int32x4_t cvt;
blkCnt = blockSize >> 2U;
/* Compute 4 outputs at a time.
** a second loop below computes the remaining 1 to 3 samples. */
while (blkCnt > 0U)
{
/* C = A * 8388608 */
/* Convert from float to q23 and then store the results in the destination buffer */
inV = vld1q_f32(pIn);
cvt = vcvtq_n_s32_f32(inV, 23);
/* saturate */
cvt = vminq_s32(cvt, vdupq_n_s32(0x007fffff));
cvt = vmaxq_s32(cvt, vdupq_n_s32(0xff800000));
vst1q_s32(pDst, cvt);
pDst += 4;
pIn += 4;
/* Decrement the loop counter */
blkCnt--;
}
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
** No loop unrolling is used. */
blkCnt = blockSize & 3;
while (blkCnt > 0U)
{
/* C = A * 8388608 */
/* Convert from float to q23 and then store the results in the destination buffer */
*pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24);
/* Decrement the loop counter */
blkCnt--;
}
}
#else
void arm_float_to_q23(const float32_t * pSrc, q23_t * pDst, uint32_t blockSize)
{
uint32_t blkCnt; /* Loop counter */
const float32_t *pIn = pSrc; /* Source pointer */
/* Loop unrolling: Compute 4 outputs at a time */
blkCnt = blockSize >> 2U;
while (blkCnt > 0U)
{
/* C = A * 8388608 */
/* convert from float to Q23 and store result in destination buffer */
*pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24);
*pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24);
*pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24);
*pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24);
/* Decrement loop counter */
blkCnt--;
}
/* Loop unrolling: Compute remaining outputs */
blkCnt = blockSize % 0x4U;
while (blkCnt > 0U)
{
/* C = A * 8388608 */
/* Convert from float to q23 and then store the results in the destination buffer */
*pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24);
/* Decrement loop counter */
blkCnt--;
}
}
#endif /* #if defined(ARM_MATH_NEON_EXPERIMENTAL) */

@ -0,0 +1,22 @@
#pragma once
#include "arm_math_types.h"
typedef int32_t q23_t;
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Converts the elements of the floating-point vector to Q23 vector.
* @param[in] pSrc points to the floating-point input vector
* @param[out] pDst points to the Q23 output vector
* @param[in] blockSize length of the input vector
*/
void arm_float_to_q23(const float32_t * pSrc, q23_t * pDst, uint32_t blockSize);
#ifdef __cplusplus
}
#endif

@ -209,7 +209,7 @@ void CConfig::Load (void)
m_INetworkIPAddress = m_Properties.GetIPAddress("NetworkIPAddress") != 0;
m_INetworkSubnetMask = m_Properties.GetIPAddress("NetworkSubnetMask") != 0;
m_INetworkDefaultGateway = m_Properties.GetIPAddress("NetworkDefaultGateway") != 0;
m_bSyslogEnabled = m_Properties.GetNumber ("SyslogEnabled", 0) != 0;
m_bSyslogEnabled = m_Properties.GetNumber ("NetworkSyslogEnabled", 0) != 0;
m_INetworkDNSServer = m_Properties.GetIPAddress("NetworkDNSServer") != 0;
const u8 *pSyslogServerIP = m_Properties.GetIPAddress ("NetworkSyslogServerIPAddress");

@ -265,6 +265,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
else
{
// Ignore any other CC messages at this time
LOGNOTE("Ignoring CC %d (%d) on Performance Select Channel %d\n", pMessage[1], pMessage[2], nPerfCh);
}
}
}

@ -29,6 +29,7 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "arm_float_to_q23.h"
const char WLANFirmwarePath[] = "SD:firmware/";
const char WLANConfigFile[] = "SD:wpa_supplicant.conf";
@ -359,7 +360,7 @@ bool CMiniDexed::Initialize (void)
return false;
}
m_pSoundDevice->SetWriteFormat (SoundFormatSigned16, Channels);
m_pSoundDevice->SetWriteFormat (SoundFormatSigned24_32, Channels);
m_nQueueSizeFrames = m_pSoundDevice->GetQueueSizeFrames ();
@ -1260,8 +1261,8 @@ void CMiniDexed::ProcessSound (void)
m_pTG[0]->getSamples (SampleBuffer, nFrames);
// Convert single float array (mono) to int16 array
int16_t tmp_int[nFrames];
arm_float_to_q15(SampleBuffer,tmp_int,nFrames);
int32_t tmp_int[nFrames];
arm_float_to_q23(SampleBuffer,tmp_int,nFrames);
if (m_pSoundDevice->Write (tmp_int, sizeof(tmp_int)) != (int) sizeof(tmp_int))
{
@ -1328,7 +1329,7 @@ void CMiniDexed::ProcessSound (void)
// Note: one TG per audio channel; output=mono; no processing.
const int Channels = 8; // One TG per channel
float32_t tmp_float[nFrames*Channels];
int16_t tmp_int[nFrames*Channels];
int32_t tmp_int[nFrames*Channels];
if(nMasterVolume > 0.0)
{
@ -1350,11 +1351,11 @@ void CMiniDexed::ProcessSound (void)
}
}
}
arm_float_to_q15(tmp_float,tmp_int,nFrames*Channels);
arm_float_to_q23(tmp_float,tmp_int,nFrames*Channels);
}
else
{
arm_fill_q15(0, tmp_int, nFrames*Channels);
arm_fill_q31(0, tmp_int, nFrames*Channels);
}
// Prevent PCM510x analog mute from kicking in
@ -1378,7 +1379,7 @@ void CMiniDexed::ProcessSound (void)
// BEGIN TG mixing
float32_t tmp_float[nFrames*2];
int16_t tmp_int[nFrames*2];
int32_t tmp_int[nFrames*2];
if(nMasterVolume > 0.0)
{
@ -1444,11 +1445,11 @@ void CMiniDexed::ProcessSound (void)
tmp_float[(i*2)+1]=SampleBuffer[indexR][i];
}
}
arm_float_to_q15(tmp_float,tmp_int,nFrames*2);
arm_float_to_q23(tmp_float,tmp_int,nFrames*2);
}
else
{
arm_fill_q15(0, tmp_int, nFrames * 2);
arm_fill_q31(0, tmp_int, nFrames * 2);
}
// Prevent PCM510x analog mute from kicking in
@ -2306,6 +2307,7 @@ void CMiniDexed::UpdateNetwork()
if (m_pConfig->GetSyslogEnabled())
{
LOGNOTE ("Syslog server is enabled in configuration");
CIPAddress ServerIP = m_pConfig->GetNetworkSyslogServerIPAddress();
if (ServerIP.IsSet () && !ServerIP.IsNull ())
{
@ -2317,6 +2319,14 @@ void CMiniDexed::UpdateNetwork()
new CSysLogDaemon (m_pNet, ServerIP, usServerPort);
}
else
{
LOGNOTE ("Syslog server IP not set");
}
}
else
{
LOGNOTE ("Syslog server is not enabled in configuration");
}
m_bNetworkReady = true;
}

@ -161,6 +161,7 @@ NetworkIPAddress=0
NetworkSubnetMask=0
NetworkDefaultGateway=0
NetworkDNSServer=0
NetworkSyslogEnabled=0
NetworkSyslogServerIPAddress=0
# Performance

@ -117,10 +117,13 @@ boolean CmDNSPublisher::UnpublishService (const char *pServiceName)
return FALSE;
}
LOGDBG ("Unpublish service %s", (const char *) pService->ServiceName);
SendResponse (pService, FALSE);
/*
if (!SendResponse (pService, TRUE))
{
LOGWARN ("Send failed");
}
*/
for (unsigned i = 0; i < pService->nTextRecords; i++)
{
delete pService->ppText[i];
@ -172,10 +175,13 @@ void CmDNSPublisher::Run (void)
TService *pService =
static_cast<TService *> (CPtrList::GetPtr (pElement));
assert (pService);
SendResponse (pService, FALSE);
/*
if (!SendResponse (pService, FALSE))
{
LOGWARN ("Send failed");
}
*/
pElement = m_ServiceList.GetNext (pElement);
}
m_Mutex.Release ();

@ -2,13 +2,13 @@
set -ex
# Update top-level modules as a baseline
git submodule update --init --recursive
git submodule update --init --recursive -f
# Use fixed master branch of circle-stdlib then re-update
cd circle-stdlib/
git reset --hard
git checkout 1111eee # Matches Circle Step49
git submodule update --init --recursive
git checkout 1111eee -f # Matches Circle Step49
git submodule update --init --recursive -f
cd -
# Optional update submodules explicitly
@ -23,5 +23,5 @@ cd -
# Use fixed master branch of Synth_Dexed
cd Synth_Dexed/
git reset --hard
git checkout 65d8383ad5
git checkout 65d8383ad5 -f
cd -

@ -0,0 +1,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Syslog server to receive and display syslog messages from MiniDexed.
"""
import socket
import time
import threading
class SyslogServer:
def __init__(self, host='0.0.0.0', port=8514):
self.host = host
self.port = port
self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.server.bind((self.host, self.port))
self.start_time = None
self.running = True
def start(self):
ip_address = socket.gethostbyname(socket.gethostname())
print(f"Syslog server listening on {ip_address}:{self.port}")
input_thread = threading.Thread(target=self.wait_for_input)
input_thread.daemon = True
input_thread.start()
while self.running:
try:
data, address = self.server.recvfrom(1024)
self.handle_message(data)
except KeyboardInterrupt:
self.running = False
def handle_message(self, data):
message = data[2:].decode('utf-8').strip()
if self.start_time is None:
self.start_time = time.time()
relative_time = "0:00:00.000"
else:
elapsed_time = time.time() - self.start_time
hours = int(elapsed_time // 3600)
minutes = int((elapsed_time % 3600) // 60)
seconds = int(elapsed_time % 60)
milliseconds = int((elapsed_time % 1) * 1000)
relative_time = f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}"
print(f"{relative_time} {message}")
def wait_for_input(self):
input("Press any key to exit...")
self.running = False
if __name__ == "__main__":
server = SyslogServer()
server.start()
print("Syslog server stopped.")
Loading…
Cancel
Save