changeset 501:6962184f8567 prerelease

Additional name changes to doxygen example title.
author Robert Jack <robert.h.jack@gmail.com>
date Wed, 22 Jun 2016 00:34:07 +0100
parents b935f890e512
children ff6e9199c444
files examples/06-Sensors/capacitive-touch/I2C_MPR121.cpp examples/06-Sensors/capacitive-touch/I2C_MPR121.h examples/06-Sensors/capacitive-touch/render.cpp examples/07-DataLogging/logging-sensors/main.cpp examples/07-DataLogging/logging-sensors/render.cpp examples/07-DataLogging/write-file/main.cpp examples/07-DataLogging/write-file/render.cpp
diffstat 7 files changed, 832 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/capacitive-touch/I2C_MPR121.cpp	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,176 @@
+/*
+ * I2C_MPR121.cpp
+ *
+ *  Created on: Oct 14, 2013
+ *      Author: Victor Zappi
+ */
+
+
+#include "I2C_MPR121.h"
+
+I2C_MPR121::I2C_MPR121() {
+
+}
+
+boolean I2C_MPR121::begin(uint8_t bus, uint8_t i2caddr) {
+  _i2c_address = i2caddr;
+	
+  if(initI2C_RW(bus, i2caddr, 0) > 0)
+	  return false;
+
+  // soft reset
+  writeRegister(MPR121_SOFTRESET, 0x63);
+  usleep(1000);
+  //delay(1);
+  for (uint8_t i=0; i<0x7F; i++) {
+  //  Serial.print("$"); Serial.print(i, HEX); 
+  //  Serial.print(": 0x"); Serial.println(readRegister8(i));
+  }
+  
+
+  writeRegister(MPR121_ECR, 0x0);
+
+  uint8_t c = readRegister8(MPR121_CONFIG2);
+  
+  if (c != 0x24) {
+	  rt_printf("MPR121 read 0x%x instead of 0x24\n", c);
+	  return false;
+  }
+
+  setThresholds(12, 6);
+  writeRegister(MPR121_MHDR, 0x01);
+  writeRegister(MPR121_NHDR, 0x01);
+  writeRegister(MPR121_NCLR, 0x0E);
+  writeRegister(MPR121_FDLR, 0x00);
+
+  writeRegister(MPR121_MHDF, 0x01);
+  writeRegister(MPR121_NHDF, 0x05);
+  writeRegister(MPR121_NCLF, 0x01);
+  writeRegister(MPR121_FDLF, 0x00);
+
+  writeRegister(MPR121_NHDT, 0x00);
+  writeRegister(MPR121_NCLT, 0x00);
+  writeRegister(MPR121_FDLT, 0x00);
+
+  writeRegister(MPR121_DEBOUNCE, 0);
+  writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
+  writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
+
+//  writeRegister(MPR121_AUTOCONFIG0, 0x8F);
+
+//  writeRegister(MPR121_UPLIMIT, 150);
+//  writeRegister(MPR121_TARGETLIMIT, 100); // should be ~400 (100 shifted)
+//  writeRegister(MPR121_LOWLIMIT, 50);
+  // enable all electrodes
+  writeRegister(MPR121_ECR, 0x8F);  // start with first 5 bits of baseline tracking
+
+  return true;
+}
+
+void I2C_MPR121::setThresholds(uint8_t touch, uint8_t release) {
+  for (uint8_t i=0; i<12; i++) {
+    writeRegister(MPR121_TOUCHTH_0 + 2*i, touch);
+    writeRegister(MPR121_RELEASETH_0 + 2*i, release);
+  }
+}
+
+uint16_t  I2C_MPR121::filteredData(uint8_t t) {
+  if (t > 12) return 0;
+  return readRegister16(MPR121_FILTDATA_0L + t*2);
+}
+
+uint16_t  I2C_MPR121::baselineData(uint8_t t) {
+  if (t > 12) return 0;
+  uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
+  return (bl << 2);
+}
+
+uint16_t  I2C_MPR121::touched(void) {
+  uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
+  return t & 0x0FFF;
+}
+
+/*********************************************************************/
+
+
+uint8_t I2C_MPR121::readRegister8(uint8_t reg) {
+    unsigned char inbuf, outbuf;
+    struct i2c_rdwr_ioctl_data packets;
+    struct i2c_msg messages[2];
+
+    /*
+     * In order to read a register, we first do a "dummy write" by writing
+     * 0 bytes to the register we want to read from.  This is similar to
+     * the packet in set_i2c_register, except it's 1 byte rather than 2.
+     */
+    outbuf = reg;
+    messages[0].addr  = 0x5A;
+    messages[0].flags = 0;
+    messages[0].len   = sizeof(outbuf);
+    messages[0].buf   = &outbuf;
+
+    /* The data will get returned in this structure */
+    messages[1].addr  = 0x5A;
+    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
+    messages[1].len   = sizeof(inbuf);
+    messages[1].buf   = &inbuf;
+
+    /* Send the request to the kernel and get the result back */
+    packets.msgs      = messages;
+    packets.nmsgs     = 2;
+    if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
+        rt_printf("Unable to send data");
+        return 0;
+    }
+
+    return inbuf;
+}
+
+uint16_t I2C_MPR121::readRegister16(uint8_t reg) {
+    unsigned char inbuf[2], outbuf;
+    struct i2c_rdwr_ioctl_data packets;
+    struct i2c_msg messages[2];
+
+    /*
+     * In order to read a register, we first do a "dummy write" by writing
+     * 0 bytes to the register we want to read from.  This is similar to
+     * the packet in set_i2c_register, except it's 1 byte rather than 2.
+     */
+    outbuf = reg;
+    messages[0].addr  = _i2c_address;
+    messages[0].flags = 0;
+    messages[0].len   = sizeof(outbuf);
+    messages[0].buf   = &outbuf;
+
+    /* The data will get returned in this structure */
+    messages[1].addr  = _i2c_address;
+    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
+    messages[1].len   = sizeof(inbuf);
+    messages[1].buf   = inbuf;
+
+    /* Send the request to the kernel and get the result back */
+    packets.msgs      = messages;
+    packets.nmsgs     = 2;
+    if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
+        rt_printf("Unable to send data");
+        return 0;
+    }
+
+    return (uint16_t)inbuf[0] | (((uint16_t)inbuf[1]) << 8);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Writes 8-bits to the specified destination register
+*/
+/**************************************************************************/
+void I2C_MPR121::writeRegister(uint8_t reg, uint8_t value) {
+	uint8_t buf[2] = { reg, value };
+
+	if(write(i2C_file, buf, 2) != 2)
+	{
+		cout << "Failed to write register " << (int)reg << " on MPR121\n";
+		return;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/capacitive-touch/I2C_MPR121.h	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,82 @@
+/*
+ * MPR121 Bela demo
+ * 
+ * Andrew McPherson
+ * Based on Adafruit library by Limor Fried/Ladyada
+ */
+
+#ifndef I2CTK_H_
+#define I2CTK_H_
+
+#include <I2c.h>
+#include "Utilities.h"
+
+typedef bool boolean;
+
+#define MPR121_I2CADDR_DEFAULT 0x5A
+
+#define MPR121_TOUCHSTATUS_L 0x00
+#define MPR121_TOUCHSTATUS_H 0x01
+#define MPR121_FILTDATA_0L  0x04
+#define MPR121_FILTDATA_0H  0x05
+#define MPR121_BASELINE_0   0x1E
+#define MPR121_MHDR         0x2B
+#define MPR121_NHDR         0x2C
+#define MPR121_NCLR         0x2D
+#define MPR121_FDLR         0x2E
+#define MPR121_MHDF         0x2F
+#define MPR121_NHDF         0x30
+#define MPR121_NCLF         0x31
+#define MPR121_FDLF         0x32
+#define MPR121_NHDT         0x33
+#define MPR121_NCLT         0x34
+#define MPR121_FDLT         0x35
+
+#define MPR121_TOUCHTH_0    0x41
+#define MPR121_RELEASETH_0    0x42
+#define MPR121_DEBOUNCE 0x5B
+#define MPR121_CONFIG1 0x5C
+#define MPR121_CONFIG2 0x5D
+#define MPR121_CHARGECURR_0 0x5F
+#define MPR121_CHARGETIME_1 0x6C
+#define MPR121_ECR 0x5E
+#define MPR121_AUTOCONFIG0 0x7B
+#define MPR121_AUTOCONFIG1 0x7C
+#define MPR121_UPLIMIT   0x7D
+#define MPR121_LOWLIMIT  0x7E
+#define MPR121_TARGETLIMIT  0x7F
+
+#define MPR121_GPIODIR  0x76
+#define MPR121_GPIOEN  0x77
+#define MPR121_GPIOSET  0x78
+#define MPR121_GPIOCLR  0x79
+#define MPR121_GPIOTOGGLE  0x7A
+
+#define MPR121_SOFTRESET 0x80
+
+class I2C_MPR121 : public I2c
+{
+public:
+	// Hardware I2C
+	I2C_MPR121();
+
+	boolean begin(uint8_t bus = 1, uint8_t i2caddr = MPR121_I2CADDR_DEFAULT);
+
+	uint16_t filteredData(uint8_t t);
+	uint16_t  baselineData(uint8_t t);
+
+	uint8_t readRegister8(uint8_t reg);
+	uint16_t readRegister16(uint8_t reg);
+	void writeRegister(uint8_t reg, uint8_t value);
+	uint16_t touched(void);
+ 
+ 	void setThresholds(uint8_t touch, uint8_t release);
+	
+	int readI2C() { return 0; } // Unused
+	
+private:
+	int _i2c_address;
+};
+
+
+#endif /* I2CTK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/capacitive-touch/render.cpp	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,171 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+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 <cmath>
+#include <rtdk.h>
+#include "I2C_MPR121.h"
+
+// How many pins there are
+#define NUM_TOUCH_PINS 12
+
+// Define this to print data to terminal
+#undef DEBUG_MPR121
+
+// Change this to change how often the MPR121 is read (in Hz)
+int readInterval = 50;
+
+// Change this threshold to set the minimum amount of touch
+int threshold = 40;
+
+// This array holds the continuous sensor values
+int sensorValue[NUM_TOUCH_PINS];
+
+// ---- test code stuff -- can be deleted for your example ----
+
+// 12 notes of a C major scale...
+float gFrequencies[NUM_TOUCH_PINS] = {261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25, 698.25, 783.99};
+
+// This is internal stuff for the demo
+float gNormFrequencies[NUM_TOUCH_PINS];
+float gPhases[NUM_TOUCH_PINS] = {0};
+
+// ---- internal stuff -- do not change -----
+
+I2C_MPR121 mpr121;			// Object to handle MPR121 sensing
+AuxiliaryTask i2cTask;		// Auxiliary task to read I2C
+
+int readCount = 0;			// How long until we read again...
+int readIntervalSamples = 0; // How many samples between reads
+
+void readMPR121();
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{
+	if(!mpr121.begin(1, 0x5A)) {
+		rt_printf("Error initialising MPR121\n");
+		return false;
+	}
+	
+	i2cTask = Bela_createAuxiliaryTask(readMPR121, 50, "bela-mpr121");
+	readIntervalSamples = context->audioSampleRate / readInterval;
+	
+	for(int i = 0; i < NUM_TOUCH_PINS; i++) {
+		gNormFrequencies[i] = 2.0 * M_PI * gFrequencies[i] / context->audioSampleRate;
+	}
+	
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numAnalogFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	for(int n = 0; n < context->audioFrames; n++) {
+		// Keep this code: it schedules the touch sensor readings
+		if(++readCount >= readIntervalSamples) {
+			readCount = 0;
+			Bela_scheduleAuxiliaryTask(i2cTask);
+		}
+		
+		float sample = 0.0;
+		
+		// This code can be replaced with your favourite audio code
+		for(int i = 0; i < NUM_TOUCH_PINS; i++) {
+			float amplitude = sensorValue[i] / 400.0;
+			
+			// Prevent clipping
+			if(amplitude > 0.5)
+				amplitude = 0.5;
+			
+			sample += amplitude * sinf(gPhases[i]);
+			gPhases[i] += gNormFrequencies[i];
+			if(gPhases[i] > 2.0 * M_PI)
+				gPhases[i] -= 2.0 * M_PI;
+		}
+		
+		for(int ch = 0; ch < context->audioChannels; ch++)
+			context->audioOut[context->audioChannels * n + ch] = sample;
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	// Nothing to do here
+}
+
+
+// Auxiliary task to read the I2C board
+void readMPR121()
+{
+	for(int i = 0; i < NUM_TOUCH_PINS; i++) {
+		sensorValue[i] = -(mpr121.filteredData(i) - mpr121.baselineData(i));
+		sensorValue[i] -= threshold;
+		if(sensorValue[i] < 0)
+			sensorValue[i] = 0;
+#ifdef DEBUG_MPR121
+		rt_printf("%d ", sensorValue[i]);
+#endif
+	}
+#ifdef DEBUG_MPR121
+	rt_printf("\n");
+#endif
+	
+	// You can use this to read binary on/off touch state more easily
+	//rt_printf("Touched: %x\n", mpr121.touched());
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 06-capacitive-touch
+
+Capacitive touch sensing with MPR121
+---------------------------
+
+This sketch allows you to hook up an MPR121 capactive touch sensing device
+to Bela, for example the SparkFun Capacitive Touch Sensor Breakout - MPR121.
+The breakout board gives you 12 electrode connections.
+
+To get this working with Bela you need to connect the breakout board to the I2C
+terminal on the Bela board. See the Pin guide for details of which pin is which.
+
+The sensor data will then be available for you to use in the array 
+`sensorValue[NUM_TOUCH_PINS]`.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/logging-sensors/main.cpp	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+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 <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;	// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/logging-sensors/render.cpp	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,73 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+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 <cmath>
+#include <WriteFile.h>
+
+WriteFile file1;
+WriteFile file2;
+
+bool setup(BelaContext *context, void *userData)
+{
+	file1.init("out.bin"); //set the file name to write to
+	file1.setEchoInterval(1000);
+	file1.setFileType(kBinary);
+	file1.setFormat("%.4f %.4f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers). When in binary mode, this is used only for echoing to console
+	file2.init("out.m"); //set the file name to write to
+	file2.setHeader("myvar=[\n"); //set one or more lines to be printed at the beginning of the file
+	file2.setFooter("];\n"); //set one or more lines to be printed at the end of the file
+	file2.setFormat("%.4f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
+	file2.setFileType(kText);
+	file2.setEchoInterval(10000); // only print to the console 1 line every other 10000
+	return true; 
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+			file1.log(&(context->analogIn[n*context->analogFrames]), 2); // log an array of values
+			file2.log(context->analogIn[n*context->analogFrames]); // log a single value
+	}
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext *context, void *userData)
+{
+    
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 07-logging-sensors
+
+Logging Sensor Data
+---------------------------
+
+This sketch demonstrates how to log sensor data for later processing or analysis.
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/write-file/main.cpp	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+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 <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;	// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/write-file/render.cpp	Wed Jun 22 00:34:07 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+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 <cmath>
+#include <WriteFile.h>
+
+float gPhase1, gPhase2;
+float gFrequency1, gFrequency2;
+float gInverseSampleRate;
+
+WriteFile file1;
+WriteFile file2;
+
+bool setup(BelaContext *context, void *userData)
+{
+	gInverseSampleRate = 1.0/context->audioSampleRate;
+	file1.init("out1.m"); //set the file name to write to
+	file1.setHeader("myvar=[\n"); //set a line to be printed at the beginning of the file
+	file1.setFooter("];\n"); //set a line to be printed at the end of the file
+	file1.setEcho(true); // enable echo to the console (as well as to the file)
+	file1.setFormat("%.5f %.10f %f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
+	file2.init("out2.m");
+	file2.setHeader("input=[\n");
+	file2.setFooter("];\n");
+	file2.setEcho(false);
+	file2.setFormat("%f\n");
+	gPhase1 = 0.0;
+	gPhase2 = 0.0;
+
+	gFrequency1 = 200.0;
+	gFrequency2 = 201.0;
+	return true; 
+}
+
+void render(BelaContext *context, void *userData)
+{
+	static int count = 0;
+	if((count&16383) == 0){
+    	file2.log(context->audioIn, context->audioFrames); //write the input buffer every so often
+	}
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+	    float chn1 = sinf(gPhase1);
+	    float chn2 = sinf(gPhase2);
+	    gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate;
+	    gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
+		if(gPhase1 > 2.0 * M_PI)
+			gPhase1 -= 2.0 * M_PI;
+		if(gPhase2 > 2.0 * M_PI)
+			gPhase2 -= 2.0 * M_PI;
+		if( (count&511) == 0){
+			file1.log(chn1);
+			file1.log(chn2);
+			file1.log(count);
+		}
+		count++;
+	}
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext *context, void *userData)
+{
+    
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 07-write-file
+
+Writing data to a file
+---------------------------
+
+This sketch demonstrates how to log values from within a project for later processing or analysis.
+
+*/
+