2025-05-08 00:58:06 +02:00
// #include "src/memllib/interface/InterfaceBase.hpp"
2025-05-10 23:54:53 +02:00
# include "display.hpp"
2025-04-28 19:32:11 +02:00
# include "src/memllib/audio/AudioAppBase.hpp"
# include "src/memllib/audio/AudioDriver.hpp"
# include "src/memllib/hardware/memlnaut/MEMLNaut.hpp"
# include <memory>
2025-05-08 00:58:06 +02:00
# include "IMLInterface.hpp"
# include "interfaceRL.hpp"
# include "hardware/structs/bus_ctrl.h"
2025-06-17 19:03:53 +02:00
# include "PAFSynthAudioApp.hpp"
2025-04-28 19:32:11 +02:00
2025-05-08 00:58:06 +02:00
# define APP_SRAM __not_in_flash("app")
2025-04-28 19:32:11 +02:00
2025-05-10 23:54:53 +02:00
display APP_SRAM scr ;
2025-04-28 19:32:11 +02:00
2025-05-08 00:58:06 +02:00
bool core1_disable_systick = true ;
bool core1_separate_stack = true ;
2025-04-28 19:32:11 +02:00
2025-05-08 00:58:06 +02:00
uint32_t get_rosc_entropy_seed ( int bits ) {
uint32_t seed = 0 ;
for ( int i = 0 ; i < bits ; + + i ) {
// Wait for a bit of time to allow jitter to accumulate
busy_wait_us_32 ( 5 ) ;
// Pull LSB from ROSC rand output
seed < < = 1 ;
seed | = ( rosc_hw - > randombit & 1 ) ;
2025-04-28 19:32:11 +02:00
}
2025-05-08 00:58:06 +02:00
return seed ;
}
2025-05-02 19:19:38 +02:00
2025-04-29 07:58:12 +02:00
2025-04-28 19:32:11 +02:00
// Global objects
2025-05-08 00:58:06 +02:00
std : : shared_ptr < IMLInterface > APP_SRAM interfaceIML ;
std : : shared_ptr < interfaceRL > APP_SRAM RLInterface ;
2025-06-17 19:03:53 +02:00
std : : shared_ptr < PAFSynthAudioApp > __scratch_y ( " audio " ) audio_app ;
2025-04-28 19:32:11 +02:00
// Inter-core communication
2025-05-08 00:58:06 +02:00
volatile bool APP_SRAM core_0_ready = false ;
volatile bool APP_SRAM core_1_ready = false ;
volatile bool APP_SRAM serial_ready = false ;
volatile bool APP_SRAM interface_ready = false ;
2025-04-28 19:32:11 +02:00
// We're only bound to the joystick inputs (x, y, rotate)
2025-05-08 00:58:06 +02:00
constexpr size_t kN_InputParams = 3 ;
2025-04-28 19:32:11 +02:00
// Add these macros near other globals
# define MEMORY_BARRIER() __sync_synchronize()
# define WRITE_VOLATILE(var, val) do { MEMORY_BARRIER(); (var) = (val); MEMORY_BARRIER(); } while (0)
# define READ_VOLATILE(var) ({ MEMORY_BARRIER(); typeof(var) __temp = (var); MEMORY_BARRIER(); __temp; })
2025-05-08 00:58:06 +02:00
void bind_RL_interface ( std : : shared_ptr < interfaceRL > interface )
{
// Set up momentary switch callbacks
MEMLNaut : : Instance ( ) - > setMomA1Callback ( [ interface ] ( ) {
2025-05-10 23:54:53 +02:00
static APP_SRAM std : : vector < String > msgs = { " Wow, incredible " , " Awesome " , " That's amazing " , " Unbelievable+ " , " I love it!! " , " More of this " , " Yes!!!! " , " A-M-A-Z-I-N-G " } ;
String msg = msgs [ rand ( ) % msgs . size ( ) ] ;
2025-05-08 00:58:06 +02:00
interface - > storeExperience ( 1.f ) ;
2025-05-10 23:54:53 +02:00
Serial . println ( msg ) ;
2025-06-17 19:03:53 +02:00
2025-05-10 23:54:53 +02:00
scr . post ( msg ) ;
2025-05-08 00:58:06 +02:00
} ) ;
MEMLNaut : : Instance ( ) - > setMomA2Callback ( [ interface ] ( ) {
2025-05-10 23:54:53 +02:00
static APP_SRAM std : : vector < String > msgs = { " Awful! " , " wtf? that sucks " , " Get rid of this sound " , " Totally shite " , " I hate this " , " Why even bother? " , " New sound please! " , " No, please no!!! " , " Thumbs down " } ;
String msg = msgs [ rand ( ) % msgs . size ( ) ] ;
2025-05-08 00:58:06 +02:00
interface - > storeExperience ( - 1.f ) ;
2025-05-10 23:54:53 +02:00
Serial . println ( msg ) ;
scr . post ( msg ) ;
2025-05-08 00:58:06 +02:00
} ) ;
MEMLNaut : : Instance ( ) - > setMomB1Callback ( [ interface ] ( ) {
interface - > randomiseTheActor ( ) ;
2025-05-10 23:54:53 +02:00
interface - > generateAction ( true ) ;
2025-05-08 00:58:06 +02:00
Serial . println ( " The Actor is confused " ) ;
2025-05-10 23:54:53 +02:00
scr . post ( " Actor: i'm confused " ) ;
2025-05-08 00:58:06 +02:00
} ) ;
MEMLNaut : : Instance ( ) - > setMomB2Callback ( [ interface ] ( ) {
interface - > randomiseTheCritic ( ) ;
2025-05-10 23:54:53 +02:00
interface - > generateAction ( true ) ;
2025-05-08 00:58:06 +02:00
Serial . println ( " The Critic is confounded " ) ;
2025-05-10 23:54:53 +02:00
scr . post ( " Critic: totally confounded " ) ;
2025-05-08 00:58:06 +02:00
} ) ;
// Set up ADC callbacks
MEMLNaut : : Instance ( ) - > setJoyXCallback ( [ interface ] ( float value ) {
interface - > setState ( 0 , value ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setJoyYCallback ( [ interface ] ( float value ) {
interface - > setState ( 1 , value ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setJoyZCallback ( [ interface ] ( float value ) {
interface - > setState ( 2 , value ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setRVGain1Callback ( [ interface ] ( float value ) {
AudioDriver : : setDACVolume ( value ) ;
} ) ;
2025-05-10 23:54:53 +02:00
MEMLNaut : : Instance ( ) - > setRVX1Callback ( [ interface ] ( float value ) {
size_t divisor = 1 + ( value * 100 ) ;
String msg = " Optimise every " + String ( divisor ) ;
scr . post ( msg ) ;
interface - > setOptimiseDivisor ( divisor ) ;
Serial . println ( msg ) ;
} ) ;
2025-06-17 19:03:53 +02:00
2025-05-10 23:54:53 +02:00
2025-05-08 00:58:06 +02:00
// Set up loop callback
MEMLNaut : : Instance ( ) - > setLoopCallback ( [ interface ] ( ) {
interface - > optimiseSometimes ( ) ;
interface - > generateAction ( ) ;
} ) ;
2025-06-17 19:03:53 +02:00
2025-05-08 00:58:06 +02:00
}
void bind_IML_interface ( std : : shared_ptr < IMLInterface > interface )
2025-04-28 19:32:11 +02:00
{
// Set up momentary switch callbacks
MEMLNaut : : Instance ( ) - > setMomA1Callback ( [ interface ] ( ) {
interface - > Randomise ( ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setMomA2Callback ( [ interface ] ( ) {
interface - > ClearData ( ) ;
} ) ;
// Set up toggle switch callbacks
MEMLNaut : : Instance ( ) - > setTogA1Callback ( [ interface ] ( bool state ) {
interface - > SetTrainingMode ( state ? IMLInterface : : TRAINING_MODE : IMLInterface : : INFERENCE_MODE ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setJoySWCallback ( [ interface ] ( bool state ) {
interface - > SaveInput ( state ? IMLInterface : : STORE_VALUE_MODE : IMLInterface : : STORE_POSITION_MODE ) ;
} ) ;
// Set up ADC callbacks
MEMLNaut : : Instance ( ) - > setJoyXCallback ( [ interface ] ( float value ) {
interface - > SetInput ( 0 , value ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setJoyYCallback ( [ interface ] ( float value ) {
interface - > SetInput ( 1 , value ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setJoyZCallback ( [ interface ] ( float value ) {
interface - > SetInput ( 2 , value ) ;
} ) ;
MEMLNaut : : Instance ( ) - > setRVZ1Callback ( [ interface ] ( float value ) {
// Scale value from 0-1 range to 1-3000
value = 1.0f + ( value * 2999.0f ) ;
interface - > SetIterations ( static_cast < size_t > ( value ) ) ;
} ) ;
// Set up loop callback
MEMLNaut : : Instance ( ) - > setLoopCallback ( [ interface ] ( ) {
interface - > ProcessInput ( ) ;
} ) ;
2025-04-29 07:58:12 +02:00
MEMLNaut : : Instance ( ) - > setRVGain1Callback ( [ interface ] ( float value ) {
2025-05-02 15:57:46 +02:00
AudioDriver : : setDACVolume ( value ) ;
2025-04-29 07:58:12 +02:00
} ) ;
2025-04-28 19:32:11 +02:00
}
2025-06-17 19:03:53 +02:00
enum MLMODES { IML , RL } ;
2025-05-08 00:58:06 +02:00
MLMODES APP_SRAM mlMode = RL ;
2025-04-28 19:32:11 +02:00
2025-05-10 23:54:53 +02:00
struct repeating_timer APP_SRAM timerDisplay ;
inline bool __not_in_flash_func ( displayUpdate ) ( __unused struct repeating_timer * t ) {
scr . update ( ) ;
return true ;
}
2025-06-17 19:03:53 +02:00
2025-04-28 19:32:11 +02:00
void setup ( )
{
2025-05-08 00:58:06 +02:00
2025-05-10 23:54:53 +02:00
scr . setup ( ) ;
2025-05-08 00:58:06 +02:00
bus_ctrl_hw - > priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS |
BUSCTRL_BUS_PRIORITY_DMA_R_BITS | BUSCTRL_BUS_PRIORITY_PROC1_BITS ;
uint32_t seed = get_rosc_entropy_seed ( 32 ) ;
srand ( seed ) ;
2025-04-28 19:32:11 +02:00
Serial . begin ( 115200 ) ;
2025-05-10 23:54:53 +02:00
// while (!Serial) {}
2025-04-28 19:32:11 +02:00
Serial . println ( " Serial initialised. " ) ;
WRITE_VOLATILE ( serial_ready , true ) ;
// Setup board
MEMLNaut : : Initialize ( ) ;
pinMode ( 33 , OUTPUT ) ;
2025-05-08 00:58:06 +02:00
switch ( mlMode ) {
case IML : {
{
auto temp_interface = std : : make_shared < IMLInterface > ( ) ;
2025-06-17 19:03:53 +02:00
temp_interface - > setup ( kN_InputParams , PAFSynthAudioApp : : kN_Params ) ;
2025-05-08 00:58:06 +02:00
MEMORY_BARRIER ( ) ;
interfaceIML = temp_interface ;
MEMORY_BARRIER ( ) ;
}
// Setup interface with memory barrier protection
WRITE_VOLATILE ( interface_ready , true ) ;
// Bind interface after ensuring it's fully initialized
bind_IML_interface ( interfaceIML ) ;
Serial . println ( " Bound IML interface to MEMLNaut. " ) ;
}
break ;
case RL : {
{
auto temp_interface = std : : make_shared < interfaceRL > ( ) ;
2025-06-17 19:03:53 +02:00
temp_interface - > setup ( kN_InputParams , PAFSynthAudioApp : : kN_Params ) ;
2025-05-08 00:58:06 +02:00
MEMORY_BARRIER ( ) ;
RLInterface = temp_interface ;
MEMORY_BARRIER ( ) ;
}
// Setup interface with memory barrier protection
WRITE_VOLATILE ( interface_ready , true ) ;
// Bind interface after ensuring it's fully initialized
bind_RL_interface ( RLInterface ) ;
Serial . println ( " Bound RL interface to MEMLNaut. " ) ;
}
break ;
2025-04-28 19:32:11 +02:00
}
WRITE_VOLATILE ( core_0_ready , true ) ;
while ( ! READ_VOLATILE ( core_1_ready ) ) {
MEMORY_BARRIER ( ) ;
delay ( 1 ) ;
}
2025-05-10 23:54:53 +02:00
scr . post ( " MEMLNaut: let's go! " ) ;
add_repeating_timer_ms ( - 39 , displayUpdate , NULL , & timerDisplay ) ;
2025-04-28 19:32:11 +02:00
Serial . println ( " Finished initialising core 0. " ) ;
}
void loop ( )
{
2025-06-17 19:03:53 +02:00
2025-05-08 00:58:06 +02:00
2025-04-28 19:32:11 +02:00
MEMLNaut : : Instance ( ) - > loop ( ) ;
2025-05-05 14:20:05 +02:00
static int AUDIO_MEM blip_counter = 0 ;
2025-04-28 19:32:11 +02:00
if ( blip_counter + + > 100 ) {
blip_counter = 0 ;
Serial . println ( " . " ) ;
// Blink LED
digitalWrite ( 33 , HIGH ) ;
} else {
// Un-blink LED
digitalWrite ( 33 , LOW ) ;
}
2025-05-08 00:58:06 +02:00
delay ( 10 ) ; // Add a small delay to avoid flooding the serial output
2025-04-28 19:32:11 +02:00
}
void setup1 ( )
{
while ( ! READ_VOLATILE ( serial_ready ) ) {
MEMORY_BARRIER ( ) ;
delay ( 1 ) ;
}
while ( ! READ_VOLATILE ( interface_ready ) ) {
MEMORY_BARRIER ( ) ;
delay ( 1 ) ;
}
2025-05-08 00:58:06 +02:00
2025-04-28 19:32:11 +02:00
// Create audio app with memory barrier protection
{
2025-06-17 19:03:53 +02:00
auto temp_audio_app = std : : make_shared < PAFSynthAudioApp > ( ) ;
2025-05-08 00:58:06 +02:00
std : : shared_ptr < InterfaceBase > selectedInterface ;
if ( mlMode = = IML ) {
selectedInterface = std : : dynamic_pointer_cast < InterfaceBase > ( interfaceIML ) ;
} else {
selectedInterface = std : : dynamic_pointer_cast < InterfaceBase > ( RLInterface ) ;
}
temp_audio_app - > Setup ( AudioDriver : : GetSampleRate ( ) , selectedInterface ) ;
// temp_audio_app->Setup(AudioDriver::GetSampleRate(), dynamic_cast<std::shared_ptr<InterfaceBase>> (mlMode == IML ? interfaceIML : RLInterface));
2025-04-28 19:32:11 +02:00
MEMORY_BARRIER ( ) ;
audio_app = temp_audio_app ;
MEMORY_BARRIER ( ) ;
}
// Start audio driver
AudioDriver : : Setup ( ) ;
WRITE_VOLATILE ( core_1_ready , true ) ;
while ( ! READ_VOLATILE ( core_0_ready ) ) {
MEMORY_BARRIER ( ) ;
delay ( 1 ) ;
}
Serial . println ( " Finished initialising core 1. " ) ;
}
void loop1 ( )
{
// Audio app parameter processing loop
audio_app - > loop ( ) ;
2025-05-10 23:54:53 +02:00
delay ( 1 ) ;
2025-04-28 19:32:11 +02:00
}
2025-05-02 19:19:38 +02:00