Can you help me integrate L3GD20H Gyro in a custom render.cpp to use it with PD?
I downloaded the library: https://github.com/adafruit/Adafruit_L3GD20
I uploaded Adafruit_L3GD20.h to Bela
I tried to integrate Adafruit_L3GD20.cpp in a custom render.cpp (copied the code into) but i got some errors.

I'll attach the custom render.cpp that that I use with Ultrasonic that is the one where i want to integrate the Gyro too.

Thanks a lot

/***** render.cpp *****/
/* mod by tomme to use ULTRASONIC SENSOR in Pure Data
 ____  _____ _        _    
| __ )| ____| |      / \   
|  _ \|  _| | |     / _ \  
| |_) | |___| |___ / ___ \ 
|____/|_____|_____/_/   \_\

The platform for ultra-low latency audio and sensor processing

http://bela.io

A project of the Augmented Instruments Laboratory within the
Centre for Digital Music at Queen Mary University of London.
http://www.eecs.qmul.ac.uk/~andrewm

(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.

The Bela software is distributed under the GNU Lesser General Public License
(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
*/


#include <Bela.h>
#include <DigitalChannelManager.h>
#include <cmath>
#include <stdio.h>
#define PD_THREADED_IO
#include <libpd/z_libpd.h>
extern "C" {
#include <libpd/s_stuff.h>
};
#include <UdpServer.h>
#include <Midi.h>
#include <Scope.h>
#include <string>
#include <sstream>
#include <algorithm>



//ultrasonic
#include <Bela.h>
#include <stdlib.h>
#include <PulseIn.h>
PulseIn pulseIn;
int gTriggerInterval = 2646; // how often to send out a trigger. 2646 samples are 60ms 
int gMinPulseLength = 7; //to avoid spurious readings
unsigned int gTriggerDigitalOutPin = 0; //channel to be connected to the module's TRIGGER pin - check the pin diagram in the IDE
unsigned int gEchoDigitalInPin = 1; //channel to be connected to the modules's ECHO pin (digital pin 1) - check the pin diagram in the IDE
int gTriggerCount = 0;
int gPrintfCount = 0;
//ultrasonic end


enum { minFirstDigitalChannel = 10 };
static unsigned int gAnalogChannelsInUse;
static unsigned int gDigitalChannelsInUse;
static unsigned int gScopeChannelsInUse = 4;
static unsigned int gLibpdBlockSize;
static unsigned int gChannelsInUse;
//static const unsigned int gFirstAudioChannel = 0;
static unsigned int gFirstAnalogInChannel;
static unsigned int gFirstAnalogOutChannel;
static unsigned int gFirstDigitalChannel;
static unsigned int gLibpdDigitalChannelOffset;
static unsigned int gFirstScopeChannel;

void Bela_userSettings(BelaInitSettings *settings)
{
	settings->uniformSampleRate = 1;
	settings->interleave = 0;
	settings->analogOutputsPersist = 0;
}

float* gInBuf;
float* gOutBuf;
#define PARSE_MIDI
static std::vector<Midi*> midi;
std::vector<std::string> gMidiPortNames;

void dumpMidi()
{
	if(midi.size() == 0)
	{
		printf("No MIDI device enabled\n");
		return;
	}
	printf("The following MIDI devices are enabled:\n");
	printf("%4s%20s %3s %3s %s\n",
			"Num",
			"Name",
			"In",
			"Out",
			"Pd channels"
	      );
	for(unsigned int n = 0; n < midi.size(); ++n)
	{
		printf("[%2d]%20s %3s %3s (%d-%d)\n", 
			n,
			gMidiPortNames[n].c_str(),
			midi[n]->isInputEnabled() ? "x" : "_",
			midi[n]->isOutputEnabled() ? "x" : "_",
			n * 16 + 1,
			n * 16 + 16
		);
	}
}

Midi* openMidiDevice(std::string name, bool verboseSuccess = false, bool verboseError = false)
{
	Midi* newMidi;
	newMidi = new Midi();
	newMidi->readFrom(name.c_str());
	newMidi->writeTo(name.c_str());
#ifdef PARSE_MIDI
	newMidi->enableParser(true);
#else
	newMidi->enableParser(false);
#endif /* PARSE_MIDI */
	if(newMidi->isOutputEnabled())
	{
		if(verboseSuccess)
			printf("Opened MIDI device %s as output\n", name.c_str());
	}
	if(newMidi->isInputEnabled())
	{
		if(verboseSuccess)
			printf("Opened MIDI device %s as input\n", name.c_str());
	}
	if(!newMidi->isInputEnabled() && !newMidi->isOutputEnabled())
	{
		if(verboseError)
			fprintf(stderr, "Failed to open  MIDI device %s\n", name.c_str());
		return nullptr;
	} else {
		return newMidi;
	}
}

static unsigned int getPortChannel(int* channel){
	unsigned int port = 0;
	while(*channel > 16){
		*channel -= 16;
		port += 1;
	}
	if(port >= midi.size()){
		// if the port number exceeds the number of ports available, send out
		// of the first port 
		rt_fprintf(stderr, "Port out of range, using port 0 instead\n");
		port = 0;
	}
	return port;
}

void Bela_MidiOutNoteOn(int channel, int pitch, int velocity) {
	int port = getPortChannel(&channel);
	rt_printf("noteout _ port: %d, channel: %d, pitch: %d, velocity %d\n", port, channel, pitch, velocity);
	midi[port]->writeNoteOn(channel, pitch, velocity);
}

void Bela_MidiOutControlChange(int channel, int controller, int value) {
	int port = getPortChannel(&channel);
	rt_printf("ctlout _ port: %d, channel: %d, controller: %d, value: %d\n", port, channel, controller, value);
	midi[port]->writeControlChange(channel, controller, value);
}

void Bela_MidiOutProgramChange(int channel, int program) {
	int port = getPortChannel(&channel);
	rt_printf("pgmout _ port: %d, channel: %d, program: %d\n", port, channel, program);
	midi[port]->writeProgramChange(channel, program);
}

void Bela_MidiOutPitchBend(int channel, int value) {
	int port = getPortChannel(&channel);
	rt_printf("bendout _ port: %d, channel: %d, value: %d\n", port, channel, value);
	midi[port]->writePitchBend(channel, value);
}

void Bela_MidiOutAftertouch(int channel, int pressure){
	int port = getPortChannel(&channel);
	rt_printf("touchout _ port: %d, channel: %d, pressure: %d\n", port, channel, pressure);
	midi[port]->writeChannelPressure(channel, pressure);
}

void Bela_MidiOutPolyAftertouch(int channel, int pitch, int pressure){
	int port = getPortChannel(&channel);
	rt_printf("polytouchout _ port: %d, channel: %d, pitch: %d, pressure: %d\n", port, channel, pitch, pressure);
	midi[port]->writePolyphonicKeyPressure(channel, pitch, pressure);
}

void Bela_MidiOutByte(int port, int byte){
	rt_printf("port: %d, byte: %d\n", port, byte);
	if(port > (int)midi.size()){
		// if the port is out of range, redirect to the first port.
		rt_fprintf(stderr, "Port out of range, using port 0 instead\n");
		port = 0;
	}
	midi[port]->writeOutput(byte);
}

void Bela_printHook(const char *received){
	rt_printf("%s", received);
}

static DigitalChannelManager dcm;

void sendDigitalMessage(bool state, unsigned int delay, void* receiverName){
	libpd_float((const char*)receiverName, (float)state);
//	rt_printf("%s: %d\n", (char*)receiverName, state);
}

void Bela_messageHook(const char *source, const char *symbol, int argc, t_atom *argv){
	if(strcmp(source, "bela_setMidi") == 0){
		int num[3] = {0, 0, 0};
		for(int n = 0; n < argc && n < 3; ++n)
		{
			if(!libpd_is_float(&argv[n]))
			{
				fprintf(stderr, "Wrong format for Bela_setMidi, expected:[hw 1 0 0(");
				return;
			}
			num[n] = libpd_get_float(&argv[n]);
		}
		std::ostringstream deviceName;
		deviceName << symbol << ":" << num[0] << "," << num[1] << "," << num[2];
		printf("Adding Midi device: %s\n", deviceName.str().c_str());
		Midi* newMidi = openMidiDevice(deviceName.str(), false, true);
		if(newMidi)
		{
			midi.push_back(newMidi);
			gMidiPortNames.push_back(deviceName.str());
		}
		dumpMidi();
		return;
	}
	if(strcmp(source, "bela_setDigital") == 0){
		// symbol is the direction, argv[0] is the channel, argv[1] (optional)
		// is signal("sig" or "~") or message("message", default) rate
		bool isMessageRate = true; // defaults to message rate
		bool direction = 0; // initialize it just to avoid the compiler's warning
		bool disable = false;
		if(strcmp(symbol, "in") == 0){
			direction = INPUT;
		} else if(strcmp(symbol, "out") == 0){
			direction = OUTPUT;
		} else if(strcmp(symbol, "disable") == 0){
			disable = true;
		} else {
			return;
		}
		if(argc == 0){
			return;
		} else if (libpd_is_float(&argv[0]) == false){
			return;
		}
		int channel = libpd_get_float(&argv[0]) - gLibpdDigitalChannelOffset;
		if(disable == true){
			dcm.unmanage(channel);
			return;
		}
		if(argc >= 2){
			t_atom* a = &argv[1];
			if(libpd_is_symbol(a)){
				char *s = libpd_get_symbol(a);
				if(strcmp(s, "~") == 0  || strncmp(s, "sig", 3) == 0){
					isMessageRate = false;
				}
			}
		}
		dcm.manage(channel, direction, isMessageRate);
		return;
	}
}

void Bela_floatHook(const char *source, float value){


	// let's make this as optimized as possible for built-in digital Out parsing
	// the built-in digital receivers are of the form "bela_digitalOutXX" where XX is between gLibpdDigitalChannelOffset and (gLibpdDigitalCHannelOffset+gDigitalChannelsInUse)
	static int prefixLength = 15; // strlen("bela_digitalOut")
	if(strncmp(source, "bela_digitalOut", prefixLength)==0){
		if(source[prefixLength] != 0){ //the two ifs are used instead of if(strlen(source) >= prefixLength+2)
			if(source[prefixLength + 1] != 0){
				// quickly convert the suffix to integer, assuming they are numbers, avoiding to call atoi
				int receiver = ((source[prefixLength] - 48) * 10);
				receiver += (source[prefixLength+1] - 48);
				unsigned int channel = receiver - gLibpdDigitalChannelOffset; // go back to the actual Bela digital channel number
				if(channel < gDigitalChannelsInUse){ //number of digital channels
					dcm.setValue(channel, value);
				}
			}
		}
	}
}



std::vector<std::string> gReceiverInputNames;
std::vector<std::string> gReceiverOutputNames;
void generateDigitalNames(unsigned int numDigitals, unsigned int libpdOffset, std::vector<std::string>& receiverInputNames, std::vector<std::string>& receiverOutputNames)
{
	std::string inBaseString = "bela_digitalIn";
	std::string outBaseString = "bela_digitalOut";
	for(unsigned int i = 0; i<numDigitals; i++)
	{
		receiverInputNames.push_back(inBaseString + std::to_string(i+libpdOffset));
		receiverOutputNames.push_back(outBaseString + std::to_string(i+libpdOffset));
	}
}

void printDigitalNames(std::vector<std::string>& receiverInputNames, std::vector<std::string>& receiverOutputNames)
{
	printf("DIGITAL INPUTS\n");
	for(unsigned int i=0; i<gDigitalChannelsInUse; i++)
		printf("%s\n", receiverInputNames[i].c_str());
	printf("DIGITAL OUTPUTS\n");
	for(unsigned int i=0; i<gDigitalChannelsInUse; i++)
		printf("%s\n", receiverOutputNames[i].c_str());
}

static char multiplexerArray[] = {"bela_multiplexer"};
static int multiplexerArraySize = 0;
static bool pdMultiplexerActive = false;

#ifdef PD_THREADED_IO
void fdLoop(void* arg){
	while(!gShouldStop){
		sys_doio();
		usleep(3000);
	}
}
#endif /* PD_THREADED_IO */

Scope scope;
float* gScopeOut;
void* gPatch;
bool gDigitalEnabled = 0;

bool setup(BelaContext *context, void *userData)
{
	
	//ultrasonic
	// Set the mode of digital pins
    pinMode(context, 0, gEchoDigitalInPin, INPUT); // receiving from ECHO PIN
    pinMode(context, 0, gTriggerDigitalOutPin, OUTPUT); // send to TRIGGER PIN
    pulseIn.init(context, gEchoDigitalInPin, HIGH); //detect HIGH pulses on this pin
	//ultrasonic end
	
	
	
	// Check Pd's version
	int major, minor, bugfix;
	sys_getversion(&major, &minor, &bugfix);
	printf("Running Pd %d.%d-%d\n", major, minor, bugfix);
	// We requested in Bela_userSettings() to have uniform sampling rate for audio
	// and analog and non-interleaved buffers.
	// So let's check this actually happened
	if(context->analogSampleRate != context->audioSampleRate)
	{
		fprintf(stderr, "The sample rate of analog and audio must match. Try running with --uniform-sample-rate\n");
		return false;
	}
	if(context->flags & BELA_FLAG_INTERLEAVED)
	{
		fprintf(stderr, "The audio and analog channels must be interleaved.\n");
		return false;
	}

	if(context->digitalFrames > 0 && context->digitalChannels > 0)
		gDigitalEnabled = 1;
	

	// add here other devices you need 
	gMidiPortNames.push_back("hw:1,0,0");
	//gMidiPortNames.push_back("hw:0,0,0");
	//gMidiPortNames.push_back("hw:1,0,1");

	scope.setup(gScopeChannelsInUse, context->audioSampleRate);
	gScopeOut = new float[gScopeChannelsInUse];

	// Check first of all if the patch file exists. Will actually open it later.
	char file[] = "_main.pd";
	char folder[] = "./";
	unsigned int strSize = strlen(file) + strlen(folder) + 1;
	char* str = (char*)malloc(sizeof(char) * strSize);
	snprintf(str, strSize, "%s%s", folder, file);
	if(access(str, F_OK) == -1 ) {
		printf("Error file %s/%s not found. The %s file should be your main patch.\n", folder, file, file);
		return false;
	}
	free(str);

	// analog setup
	gAnalogChannelsInUse = context->analogInChannels;
	gDigitalChannelsInUse = context->digitalChannels;
	printf("Audio channels in use: %d\n", context->audioOutChannels);
	printf("Analog channels in use: %d\n", gAnalogChannelsInUse);
	printf("Digital channels in use: %d\n", gDigitalChannelsInUse);

	// Channel distribution
	gFirstAnalogInChannel = std::max(context->audioInChannels, context->audioOutChannels);
	gFirstAnalogOutChannel = gFirstAnalogInChannel;
	gFirstDigitalChannel = gFirstAnalogInChannel + std::max(context->analogInChannels, context->analogOutChannels);
	if(gFirstDigitalChannel < minFirstDigitalChannel)
		gFirstDigitalChannel = minFirstDigitalChannel; //for backwards compatibility
	gLibpdDigitalChannelOffset = gFirstDigitalChannel + 1;
	gFirstScopeChannel = gFirstDigitalChannel + gDigitalChannelsInUse;

	gChannelsInUse = gFirstScopeChannel + gScopeChannelsInUse;
	
	// Create receiverNames for digital channels
	generateDigitalNames(gDigitalChannelsInUse, gLibpdDigitalChannelOffset, gReceiverInputNames, gReceiverOutputNames);
	
	// digital setup
	if(gDigitalEnabled)
	{
		dcm.setCallback(sendDigitalMessage);
		if(gDigitalChannelsInUse > 0){
			for(unsigned int ch = 0; ch < gDigitalChannelsInUse; ++ch){
				dcm.setCallbackArgument(ch, (void*) gReceiverInputNames[ch].c_str());
			}
		}
	}

	unsigned int n = 0;
	while(n < gMidiPortNames.size())
	{
		Midi* newMidi = openMidiDevice(gMidiPortNames[n], false, false);
		if(newMidi)
		{
			midi.push_back(newMidi);
			++n;
		} else {
			gMidiPortNames.erase(gMidiPortNames.begin() + n);
		}
	}
	dumpMidi();

	// check that we are not running with a blocksize smaller than gLibPdBlockSize
	gLibpdBlockSize = libpd_blocksize();
	if(context->audioFrames < gLibpdBlockSize){
		fprintf(stderr, "Error: minimum block size must be %d\n", gLibpdBlockSize);
		return false;
	}

	// set hooks before calling libpd_init
	libpd_set_printhook(Bela_printHook);
	libpd_set_floathook(Bela_floatHook);
	libpd_set_messagehook(Bela_messageHook);
	libpd_set_noteonhook(Bela_MidiOutNoteOn);
	libpd_set_controlchangehook(Bela_MidiOutControlChange);
	libpd_set_programchangehook(Bela_MidiOutProgramChange);
	libpd_set_pitchbendhook(Bela_MidiOutPitchBend);
	libpd_set_aftertouchhook(Bela_MidiOutAftertouch);
	libpd_set_polyaftertouchhook(Bela_MidiOutPolyAftertouch);
	libpd_set_midibytehook(Bela_MidiOutByte);

	//initialize libpd. This clears the search path
	libpd_init();
	//Add the current folder to the search path for externals
	libpd_add_to_search_path(".");
	libpd_add_to_search_path("../pd-externals");

	libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate);
	gInBuf = get_sys_soundin();
	gOutBuf = get_sys_soundout();

	// start DSP:
	// [; pd dsp 1(
	libpd_start_message(1);
	libpd_add_float(1.0f);
	libpd_finish_message("pd", "dsp");

	// Bind your receivers here
	for(unsigned int i = 0; i < gDigitalChannelsInUse; i++)
		libpd_bind(gReceiverOutputNames[i].c_str());
	libpd_bind("bela_setDigital");
	libpd_bind("bela_setMidi");

	// open patch:
	gPatch = libpd_openfile(file, folder);
	if(gPatch == NULL){
		printf("Error: file %s/%s is corrupted.\n", folder, file); 
		return false;
	}

	// If the user wants to use the multiplexer capelet,
	// the patch will have to contain an array called "bela_multiplexer"
	// and a receiver [r bela_multiplexerChannels]
	if(context->multiplexerChannels > 0 && libpd_arraysize(multiplexerArray) >= 0){
		pdMultiplexerActive = true;
		multiplexerArraySize = context->multiplexerChannels * context->analogInChannels;
		// [; bela_multiplexer ` multiplexerArraySize` resize(
		libpd_start_message(1);
		libpd_add_float(multiplexerArraySize);
		libpd_finish_message(multiplexerArray, "resize");
		// [; bela_multiplexerChannels `context->multiplexerChannels`(
		libpd_float("bela_multiplexerChannels", context->multiplexerChannels);
	}

	// Tell Pd that we will manage the io loop,
	// and we do so in an Auxiliary Task
#ifdef PD_THREADED_IO
	sys_dontmanageio(1);
	AuxiliaryTask fdTask;
	fdTask = Bela_createAuxiliaryTask(fdLoop, 50, "libpd-fdTask", NULL);
	Bela_scheduleAuxiliaryTask(fdTask);
#endif /* PD_THREADED_IO */

	dcm.setVerbose(false);
	return true;
}

void render(BelaContext *context, void *userData)
{
	
	//ultrasonic
	 for(unsigned int n = 0; n<context->digitalFrames; n++){
        gTriggerCount++;
        if(gTriggerCount == gTriggerInterval){
            gTriggerCount = 0;
            digitalWriteOnce(context, n / 2, gTriggerDigitalOutPin, HIGH); //write the status to the trig pin
        } else {
            digitalWriteOnce(context, n / 2, gTriggerDigitalOutPin, LOW); //write the status to the trig pin
        }
        int pulseLength = pulseIn.hasPulsed(context, n); // will return the pulse duration(in samples) if a pulse just ended 
        float duration = 1e6 * pulseLength / context->digitalSampleRate; // pulse duration in microseconds
        static float distance = 0;
        if(pulseLength >= gMinPulseLength){
            static int count = 0;
            duration = constrain(duration, 200, 900);
            distance = ((duration - 200) / 700);
            libpd_float("ultra1", distance);
            ++count;
        }

    }
    //ultrasonic end
	
	
	
	int num;
#ifdef PARSE_MIDI
	for(unsigned int port = 0; port < midi.size(); ++port){
		while((num = midi[port]->getParser()->numAvailableMessages()) > 0){
			static MidiChannelMessage message;
			message = midi[port]->getParser()->getNextChannelMessage();
			rt_printf("On port %d (%s): ", port, gMidiPortNames[port].c_str());
			message.prettyPrint(); // use this to print beautified message (channel, data bytes)
			switch(message.getType()){
				case kmmNoteOn:
				{
					int noteNumber = message.getDataByte(0);
					int velocity = message.getDataByte(1);
					int channel = message.getChannel();
					libpd_noteon(channel + port * 16, noteNumber, velocity);
					break;
				}
				case kmmNoteOff:
				{
					/* PureData does not seem to handle noteoff messages as per the MIDI specs,
					 * so that the noteoff velocity is ignored. Here we convert them to noteon
					 * with a velocity of 0.
					 */
					int noteNumber = message.getDataByte(0);
	//				int velocity = message.getDataByte(1); // would be ignored by Pd
					int channel = message.getChannel();
					libpd_noteon(channel + port * 16, noteNumber, 0);
					break;
				}
				case kmmControlChange:
				{
					int channel = message.getChannel();
					int controller = message.getDataByte(0);
					int value = message.getDataByte(1);
					libpd_controlchange(channel + port * 16, controller, value);
					break;
				}
				case kmmProgramChange:
				{
					int channel = message.getChannel();
					int program = message.getDataByte(0);
					libpd_programchange(channel + port * 16, program);
					break;
				}
				case kmmPolyphonicKeyPressure:
				{
					int channel = message.getChannel();
					int pitch = message.getDataByte(0);
					int value = message.getDataByte(1);
					libpd_polyaftertouch(channel + port * 16, pitch, value);
					break;
				}
				case kmmChannelPressure:
				{
					int channel = message.getChannel();
					int value = message.getDataByte(0);
					libpd_aftertouch(channel + port * 16, value);
					break;
				}
				case kmmPitchBend:
				{
					int channel = message.getChannel();
					int value =  ((message.getDataByte(1) << 7)| message.getDataByte(0)) - 8192;
					libpd_pitchbend(channel + port * 16, value);
					break;
				}
				case kmmSystem:
				// currently Bela only handles sysrealtime, and it does so pretending it is a channel message with no data bytes, so we have to re-assemble the status byte
				{
					int channel = message.getChannel();
					int status = message.getStatusByte();
					int byte = channel | status;
					libpd_sysrealtime(port, byte);
					break;
				}
				case kmmNone:
				case kmmAny:
					break;
			}
		}
	}
#else
	int input;
	for(unsigned int port = 0; port < NUM_MIDI_PORTS; ++port){
		while((input = midi[port].getInput()) >= 0){
			libpd_midibyte(port, input);
		}
	}
#endif /* PARSE_MIDI */
	unsigned int numberOfPdBlocksToProcess = context->audioFrames / gLibpdBlockSize;

	// Remember: we have non-interleaved buffers and the same sampling rate for
	// analogs, audio and digitals
	for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick)
	{
		//audio input
		for(int n = 0; n < context->audioInChannels; ++n)
		{
			memcpy(
				gInBuf + n * gLibpdBlockSize,
				context->audioIn + tick * gLibpdBlockSize + n * context->audioFrames, 
				sizeof(context->audioIn[0]) * gLibpdBlockSize
			);
		}

		// analog input
		for(int n = 0; n < context->analogInChannels; ++n)
		{
			memcpy(
				gInBuf + gLibpdBlockSize * gFirstAnalogInChannel + n * gLibpdBlockSize,
				context->analogIn + tick * gLibpdBlockSize + n * context->analogFrames, 
				sizeof(context->analogIn[0]) * gLibpdBlockSize
			);
		}
		// multiplexed analog input
		if(pdMultiplexerActive)
		{
			// we do not disable regular analog inputs if muxer is active, because user may have bridged them on the board and
			// they may be using half of them at a high sampling-rate
			static int lastMuxerUpdate = 0;
			if(++lastMuxerUpdate == multiplexerArraySize){
				lastMuxerUpdate = 0;
				libpd_write_array(multiplexerArray, 0, (float *const)context->multiplexerAnalogIn, multiplexerArraySize);
			}
		}

		unsigned int digitalFrameBase = gLibpdBlockSize * tick;
		unsigned int j;
		unsigned int k;
		float* p0;
		float* p1;
		// digital input
		if(gDigitalEnabled)
		{
			// digital in at message-rate
			dcm.processInput(&context->digital[digitalFrameBase], gLibpdBlockSize);

			// digital in at signal-rate
			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
				unsigned int digitalFrame = digitalFrameBase + j;
				for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstDigitalChannel;
						k < 16; ++k, p1 += gLibpdBlockSize) {
					if(dcm.isSignalRate(k) && dcm.isInput(k)){ // only process input channels that are handled at signal rate
						*p1 = digitalRead(context, digitalFrame, k);
					}
				}
			}
		}

		libpd_process_sys(); // process the block

		// digital outputs
		if(gDigitalEnabled)
		{
			// digital out at signal-rate
			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
				unsigned int digitalFrame = (digitalFrameBase + j);
				for (k = 0, p1 = p0  + gLibpdBlockSize * gFirstDigitalChannel;
					k < context->digitalChannels; k++, p1 += gLibpdBlockSize)
				{
					if(dcm.isSignalRate(k) && dcm.isOutput(k)){ // only process output channels that are handled at signal rate
						digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5);
					}
				}
			}

			// digital out at message-rate
			dcm.processOutput(&context->digital[digitalFrameBase], gLibpdBlockSize);
		}

		// scope output
		for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
			for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstScopeChannel; k < gScopeChannelsInUse; k++, p1 += gLibpdBlockSize) {
				gScopeOut[k] = *p1;
			}
			scope.log(gScopeOut[0], gScopeOut[1], gScopeOut[2], gScopeOut[3]);
		}
		

		
		// audio output
		for(int n = 0; n < context->audioOutChannels; ++n)
		{
			memcpy(
				context->audioOut + tick * gLibpdBlockSize + n * context->audioFrames, 
				gOutBuf + n * gLibpdBlockSize,
				sizeof(context->audioOut[0]) * gLibpdBlockSize
			);
		}

		//analog output
		for(int n = 0; n < context->analogOutChannels; ++n)
		{
			memcpy(
				context->analogOut + tick * gLibpdBlockSize + n * context->analogFrames, 
				gOutBuf + gLibpdBlockSize * gFirstAnalogOutChannel + n * gLibpdBlockSize,
				sizeof(context->analogOut[0]) * gLibpdBlockSize
			);
		}
	}
}

void cleanup(BelaContext *context, void *userData)
{
	for(auto a : midi)
	{
		delete a;
	}
	libpd_closefile(gPatch);
	delete [] gScopeOut;
}

    tomme Can you help me integrate L3GD20H Gyro in a custom render.cpp to use it with PD?
    I downloaded the library: https://github.com/adafruit/Adafruit_L3GD20
    I uploaded Adafruit_L3GD20.h to Bela
    I tried to integrate Adafruit_L3GD20.cpp in a custom render.cpp (copied the code into) but i got some errors.

    This approach wouldn't work: you will get some compile time error because the files #include'd by the program do not exist, as they are Arduino-specific.

    Normally, to connect a given device on Bela, the procedure is something like:
    - look for existing Linux drivers/libraries.
    - failing that, look for existing Arduino libraries.

    If you have an existing Linux driver/library, read through the documentation and try to build their minimal example. Sometimes there will be some board-specific changes to be made, in case it was developed with a different platform in mind. Often it will just work out of the box.

    If you only have an Arduino library, then the porting of that is going to be more complicated and involved, however - again - you should try to build a minimal working example first.

    Once you have a minimal working example built, you shall then try to integrate it in a Bela project. First, in a plain C++ project, where you call the initialization routines in setup() and the actual I/O in an AuxiliaryTask.
    Once you also have this working, you can then move on and integrate it in a custom libpd render.

    So

    • look for existing Linux drivers/libraries.

    I did that, and RTIMULib seems to support your IMU. So, I downloaded it, copied the files to the board, and tried to build some of the test programs. They build fine and they fail at runtime, as expected, because I don't actually have any IMU here.

    So you could do the same, but with the IMU:
    - plug in the IMU
    - get the code from https://github.com/RPi-Distro/RTIMULib on to the board (e.g.: assuming you have downloaded the code and you have folder containing it on your desktop, open a terminal and type scp -r ~/Desktop/RTIMULib root@192.168.7.2:RTIMULib (or scp -r ~/Desktop/RTIMULib root@192.168.6.2:RTIMULib if you are on Windows)
    - ssh into the board (e.g.: in the terminal type ssh root@192.168.7.2 (or ssh root@192.168.6.2 if you are on Windows))
    - run the following on the board:

    cd /root/RTIMULib/Linux/RTIMULibDrive
    make
     ./Output/RTIMULibDrive

    this should build the demo program, and the last line will run it. Once it runs, it should automatically detect your IMU.

    There is another demo program for calibration:

    cd /root/RTIMULib/Linux/RTIMULibCal
    make
     ./Output/RTIMULibCal

    Once you have a minimal working example built, you shall then try to integrate it in a Bela project. First, in a plain C++ project, where you call the initialization routines in setup() and the actual I/O in an AuxiliaryTask.
    Once you also have this working, you can then move on and integrate it in a custom libpd render.

    tomme I'll attach the custom render.cpp that that I use with Ultrasonic that is the one where i want to integrate the Gyro too.

    It's really hard to through 600 lines of code pasted on the forum in order to look for some unspecified errors. I would recommend, if you get back to this point again after going through the above, that you post a minimal set of lines here, which amount to the changes you made, and that you provide an external link (e.g.: to a GitHub repository) where the full code is available for anyone who has the time to look into that.

    tomme but i got some errors.

    Along with the minimal set of changes, please also include the errors. It's "very difficult" to help with unspecified errors/. I can speculate that currently you are getting errors about \xyz` not declared in this scope or similar. This is because you didn't provide an appropriate include to yourrender.cpp. However, if you did that, you would then get andunable to find file WProgram.h`. This, as mentioned above, you imported an Arduino header file and it is trying to include some files that don't exist on Bela.

    Thanks and sorry for the 600 lines of code.
    I tried to follow your passages but at first one I receive an error:

    I type this on terminal:
    scp -r ~/Desktop/RTIMULib root@192.168.7.2:RTIMULib

    I get:
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that a host key has just been changed.
    The fingerprint for the ECDSA key sent by the remote host is
    SHA256:HsK2XQVCqtZSc5ACshyq3/sHWJ99nuccb4gIvqeEqjk.
    Please contact your system administrator.
    Add correct host key in /Users/tommasorosati/.ssh/known_hosts to get rid of this message.
    Offending ECDSA key in /Users/tommasorosati/.ssh/known_hosts:1
    ECDSA host key for 192.168.7.2 has changed and you have requested strict checking.
    Host key verification failed.
    lost connection

    Thanks
    ps my last post (https://forum.bela.io/d/779-drop-audio-only-on-autorun-battery-powered) is more urgent than this one, if you can.

    oh this means that you previously ssh'ed into a different board at the same IP address. To fix this, run on the terminal on your host, once:

    ssh-keygen -R "192.168.7.2"

    then try again and it should work.

    All done but no IMU detected. I connected:
    Vin -> Bela 5V
    GND -> Bela GND
    SDA -> Bela I2C SDA
    SCL -> Bela I2C SCL

    and get

    root@bela:~/RTIMULib/Linux/RTIMULibDrive# ./Output/RTIMULibDrive
    Settings file RTIMULib.ini loaded
    Failed to open SPI bus 0, select 0
    Failed to open SPI bus 0, select 1
    No IMU detected
    Using fusion algorithm RTQF
    No IMU found

    right. First off, move the power from 5V to 3.3V . Using 5V could is dangerous for Bela (as the digital pins on Bela are 3.3V tolerant). I am surprised (and happy) that it didn't blow up yet, but please change the wiring.

    After that, try running the code again. If it still fails, try the following command on the terminal and post the results:

    i2cdetect -y -r 1

    That is assuming you connected it to the I2c-1 bus, which is the one that is broken out to a dedicate connector on the Bela cape. If you used the I2c-2 bus instead, replace 1 with 2 in the command above.

    root@bela:~/RTIMULib/Linux/RTIMULibDrive# i2cdetect -y -r 1
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- 6b -- -- -- --
    70: -- -- -- -- -- -- -- --

    root@bela:~/RTIMULib/Linux/RTIMULibDrive# i2cdetect -y -r 2
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --

      Right, so the first one seems to indicate that there is something connected on the bus at address 0x6b.

      You can see in RTIMULib/IMUDrivers/RTIMUDefs.h that this address is associated with the following devices, through these defines in RTIMULib/RTIMULib/IMUDrivers/RTIMUDefs.h:

      #define MPU9150_PWR_MGMT_1          0x6b
      #define MPU9250_PWR_MGMT_1          0x6b
      #define L3GD20_ADDRESS1             0x6b
      #define L3GD20H_ADDRESS1        0x6b
      #define LSM9DS0_GYRO_ADDRESS1       0x6b
      #define LSM9DS1_ADDRESS1  0x6b

      Can you check the file RTIMULib.ini that has been generated in the ~/RTIMULib/Linux/RTIMULibDrive and see what the value is of the I2Cbus= variable? That should be set to 1.

      If you want to debug this further, maybe add some printf() statements in ~/RTIMULib/RTIMULib/RTIMUSettings.cpp. The discoverIMU() method, starting at line 69 seems to be the one where the I2C bus is scanned for IMUs, as it goes through all the known addresses.

      I2C Bus (between 0 and 7)

      I2CBus=1

      1) To insert printf() is correct "vi ~/RTIMULib/RTIMULib/RTIMUSettings.cpp"?
      2) Where I must put printf() in ~/RTIMULib/RTIMULib/RTIMUSettings.cpp ?
      3) what command must I run after printf() insertions?

        tomme 1) To insert printf() is correct "vi ~/RTIMULib/RTIMULib/RTIMUSettings.cpp"?

        Well, if you are familiar with vi, then yes! Otherwise, nano is more intuitive

        tomme 3) what command must I run after printf() insertions?

        Rebuild and rerun the program. The line below is a more generic version of the make and ./Output/RTIMULibDrive commands above. This version you can run it regardless of what folders you are currently in:

        make -C /root/RTIMULib/Linux/RTIMULibDrive/ &&  /root/RTIMULib/Linux/RTIMULibDrive/Output/RTIMULibDrive

        tomme 2) Where I must put printf() in ~/RTIMULib/RTIMULib/RTIMUSettings.cpp ?

        printf() allows to print arbitrary strings. I am suggesting that you could add a printf("mystring\n);" statement at some meaningful places, to verify that the code is indeed going through that path. The\n` symbol at the end of the string indicates "newline".
        For instance, around line 78:

            if (HALOpen()) {
                    printf("HALOpened\n");
        
                if (HALRead(MPU9150_ADDRESS0, MPU9150_WHO_AM_I, 1, &result, "")) {
                    if (result == MPU9250_ID) {

        if HALOpened is printed to the screen, then you know that the program has indeed successfully reached that line of code. You could add some more further below, around line 200:

            printf("About to read L3GD20H_ADDRESS1\n");
             if (HALRead(L3GD20H_ADDRESS1, L3GD20H_WHO_AM_I, 1, &result, "")) {
                    printf("Reading L3GD20H_ADDRESS1 was successful, WHO_AM_I returned 0x%x\n", result);
                    if (result == L3GD20H_ID) {
                        printf("The result matched L3GD20H_ID\n");
                        if (HALRead(LSM303D_ADDRESS1, LSM303D_WHO_AM_I, 1, &altResult, "")) {

        Now, if the detection was working properly, you should see printed, after the Settings file RTIMULib.ini loaded line:

        HALOpened
        About to read L3GD20H_ADDRESS1
        Reading L3GD20H_ADDRESS1 was successful, WHO_AM_I returned 0xd7
        The result matched L3GD20H_ID.

        if it is not successful, only some of these will be printed. We can then work from there.

        Note that the line

                    printf("Reading L3GD20H_ADDRESS1 was successful, WHO_AM_I returned 0x%x\n", result);

        is printing a "formatted string", where the symbol %x is replaced by the hexadecimal representation of the value stored in the variable result. If you want to know more about printf, see, e.g.: here.

        I tried on my board with a BNO055, and this library and it gets detected straight away.

        a month later

        I got

        g++ -Wl,-O1 -o Output/RTIMULibDrive objects/RTIMULibDrive.o objects/RTMath.o objects/RTIMUHal.o objects/RTFusion.o objects/RTFusionKalman4.o objects/RTFusionRTQF.o objects/RTIMUSettings.o objects/RTIMUAccelCal.o objects/RTIMUMagCal.o objects/RTIMU.o objects/RTIMUNull.o objects/RTIMUMPU9150.o objects/RTIMUMPU9250.o objects/RTIMUGD20HM303D.o objects/RTIMUGD20M303DLHC.o objects/RTIMUGD20HM303DLHC.o objects/RTIMULSM9DS0.o objects/RTIMULSM9DS1.o objects/RTIMUBMX055.o objects/RTIMUBNO055.o objects/RTPressure.o objects/RTPressureBMP180.o objects/RTPressureLPS25H.o objects/RTPressureMS5611.o objects/RTPressureMS5637.o -L/usr/lib/arm-linux-gnueabihf
        make: Leaving directory '/root/RTIMULib/Linux/RTIMULibDrive'
        Settings file not found. Using defaults and creating settings file
        HALOpened
        About to read L3GD20H_ADDRESS1
        Reading L3GD20H_ADDRESS1 was successful, WHO_AM_I returned 0xd7
        The result matched L3GD20H_ID
        Failed to open SPI bus 0, select 0
        Failed to open SPI bus 0, select 1
        No IMU detected
        Using fusion algorithm RTQF
        No IMU found

        ok, it seems that none of the internal if() is matched:
        Try adding more printf() lines, as below:

                        if (HALRead(LSM303D_ADDRESS1, LSM303D_WHO_AM_I, 1, &altResult, "")) {
                              printf("First altResult: %d\n", altResult);
                            if (altResult == LSM303D_ID) {
                                imuType = RTIMU_TYPE_GD20HM303D;
                                slaveAddress = L3GD20H_ADDRESS1;
                                busIsI2C = true;
                                HAL_INFO("Detected L3GD20H/LSM303D at option/option address\n");
                                return true;
                            }
                        }
                        else {printf("First else\n")
                        if (HALRead(LSM303D_ADDRESS0, LSM303D_WHO_AM_I, 1, &altResult, "")) {
                              printf("Second altResult: %d\n", altResult);
                            if (altResult == LSM303D_ID) {
                                imuType = RTIMU_TYPE_GD20HM303D;
                                slaveAddress = L3GD20H_ADDRESS1;
                                busIsI2C = true;
                                HAL_INFO("Detected L3GD20H/LSM303D at option/standard address\n");
                                return true;
                            }
                        }
                        else {printf("Second else\n")
                        if (HALRead(LSM303DLHC_ACCEL_ADDRESS, LSM303DLHC_STATUS_A, 1, &altResult, "")) {
                              printf("Third altResult: %d\n", altResult);
                            imuType = RTIMU_TYPE_GD20HM303DLHC;
                            slaveAddress = L3GD20H_ADDRESS1;
                            busIsI2C = true;
                            HAL_INFO("Detected L3GD20H/LSM303DLHC at option/standard address\n");
                            return true;
                        }
                       else {printf("Third else\n")
        printf("About to read L3GD20H_ADDRESS1\n");
                if (HALRead(L3GD20H_ADDRESS1, L3GD20H_WHO_AM_I, 1, &result, "")) {
                   printf("Reading L3GD20H_ADDRESS1 was successful, WHO_AM_I returned 0x%x\n", result);
                         if (result == L3GD20H_ID) {
        printf("The result matched L3GD20H_ID\n");
                if (HALRead(LSM303D_ADDRESS1, LSM303D_WHO_AM_I, 1, &altResult, "")) {
                            printf("First altResult: %d\n", altResult);
                                if (altResult == LSM303D_ID) {
                                imuType = RTIMU_TYPE_GD20HM303D;
                                slaveAddress = L3GD20H_ADDRESS1;
                                busIsI2C = true;
                                HAL_INFO("Detected L3GD20H/LSM303D at option/option address\n");
                                return true;
                            }
                        }
        else {printf("First else\n");}
                        if (HALRead(LSM303D_ADDRESS0, LSM303D_WHO_AM_I, 1, &altResult, "")) {
                            if (altResult == LSM303D_ID) {
                                imuType = RTIMU_TYPE_GD20HM303D;
                                slaveAddress = L3GD20H_ADDRESS1;
                                busIsI2C = true;
                                HAL_INFO("Detected L3GD20H/LSM303D at option/standard address\n");
                                return true;
                            }
                        }
        else {printf("Second else\n");}
                        if (HALRead(LSM303DLHC_ACCEL_ADDRESS, LSM303DLHC_STATUS_A, 1, &altResult, "")) {
                            imuType = RTIMU_TYPE_GD20HM303DLHC;
                            slaveAddress = L3GD20H_ADDRESS1;
                            busIsI2C = true;
                            HAL_INFO("Detected L3GD20H/LSM303DLHC at option/standard address\n");
                            return true;
                        }
        else {printf("Third else\n");}
                    } else if (result == LSM9DS0_GYRO_ID) {
                        if (HALRead(LSM9DS0_ACCELMAG_ADDRESS1, LSM9DS0_WHO_AM_I, 1, &altResult, "")) {
                            if (altResult == LSM9DS0_ACCELMAG_ID) {
                                imuType = RTIMU_TYPE_LSM9DS0;
                                slaveAddress = LSM9DS0_GYRO_ADDRESS1;
                                busIsI2C = true;
                                HAL_INFO("Detected LSM9DS0 at option/option address\n");
                                return true;
                            }
                        }

        Settings file RTIMULib.ini loaded
        HALOpened
        About to read L3GD20H_ADDRESS1
        Reading L3GD20H_ADDRESS1 was successful, WHO_AM_I returned 0xd7
        The result matched L3GD20H_ID

        First else
        Second else
        Third else
        Failed to open SPI bus 0, select 0
        Failed to open SPI bus 0, select 1
        No IMU detected
        Using fusion algorithm RTQF
        No IMU found

        ok that seems a bit weird. This library seems a bit more complex and flexible than the Arduino one. In
        IMUDrivers/RTIMUDefs.h it says

        #define RTIMU_TYPE_GD20M303DLHC             4                   // STM L3GD20/LSM303DHLC (old Adafruit IMU)
        ...
        #define RTIMU_TYPE_GD20HM303DLHC            8                   // STM L3GD20H/LSM303DHLC (new Adafruit IMU)

        and you probably have the latter. Then in RTIMUSettings.cpp, at the lines above it tries to detect RTIMU_TYPE_GD20HM303DLHC: the conditions for that to be detected are:

        • reading the correct WHO_AM_I register from the device located at L3GD20H_ADDRESS1 (0x6b). Your printf() statements above report that this condition is indeed satisfied
        • it then looks (in the third if/else block) for another device (an accelerometer, from the name of it) located at LSM303DLHC_ACCEL_ADDRESS (0x19). This fails: it looks like there is no such accelerometer connected.

        Here is where my confusion comes in: the Arduino code does not mention accelerometers, and does not mention address 0x19 at all.

        From this earlier post

        tomme root@bela:~/RTIMULib/Linux/RTIMULibDrive# i2cdetect -y -r 1

        >      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
        > 00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
        > 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        > 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        > 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        > 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        > 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        > 60: -- -- -- -- -- -- -- -- -- -- -- 6b -- -- -- -- 
        > 70: -- -- -- -- -- -- -- --

        it looks like - indeed - you only have one device at 0x6b, and no accelerometer at the other address. Either your device is defective, or the RTIMU library is not quite designed for the very sensor you have in your hands. Have you ever tried it on an Arduino with the Adafruit unified library ?

        You could try the following hack: brute-force set the imuType and slaveAddress, and avoid calling any accelerometer-related methods (that is: all those that use m_accelSlaveAddr in IMUDrivers/RTIMUGD20HM303DLHC.cpp, and hope that this will work. I don't know enough about the library to know whether you stand a chance or not ...
        To achieve this, you can do something like the following:
        change the third if statement:

                        if (HALRead(LSM303DLHC_ACCEL_ADDRESS, LSM303DLHC_STATUS_A, 1, &altResult, "")) {
                            imuType = RTIMU_TYPE_GD20HM303DLHC;
                            slaveAddress = L3GD20H_ADDRESS1;
                            busIsI2C = true;
                            HAL_INFO("Detected L3GD20H/LSM303DLHC at option/standard address\n");
                            return true;
                        }
        else {printf("Third else\n");}

        so that the first line always has a valid condition, i.e.:

                        if (1 || HALRead(LSM303DLHC_ACCEL_ADDRESS, LSM303DLHC_STATUS_A, 1, &altResult, "")) {
                            imuType = RTIMU_TYPE_GD20HM303DLHC;
                            slaveAddress = L3GD20H_ADDRESS1;
                            busIsI2C = true;
                            HAL_INFO("Detected L3GD20H/LSM303DLHC at option/standard address\n");
                            return true;
                        }
        else {printf("Third else\n");}

        also, it would helpful if you sent a link to the exact device you are using.