view include/Utilities.h @ 68:59edd5780fef

Changed d-box code to run cleanly when built on board. Updated Makefile to add ne10 include path on board. Some extra docs in Utilities.h
author andrewm
date Fri, 17 Jul 2015 16:57:08 +0100
parents 74a44c3d91f0
children d837fb676977
line wrap: on
line source
/**
 *  @file
 *  @brief Wiring-inspired utility functions and macros
 *
 *  Macros and functions for I/O and data processing taking after the Wiring
 *  (Arduino) language. This code began as part of the Hackable Instruments
 *  project (EPSRC) at Queen Mary University of London, 2013-14.
 *
 *  (c) 2014-15 Andrew McPherson, Victor Zappi and Giulio Moro,
 *  Queen Mary University of London
 */

#ifndef UTILITIES_H_
#define UTILITIES_H_

#include "BeagleRT.h"

/// Set the given bit in \c word to 1.
#define setBit(word,bit) 			((word) | (1 << (bit)))

/// Clear the given bit in \c word to 0.
#define clearBit(word,bit) 			((word) &~ (1 << (bit)))

/// Check if the given bit in \c word is 1 (returns nonzero) or 0 (returns zero).
#define getBit(word,bit) 			(((word) >> (bit)) & 1)

/// Set/clear the given bit in \c word to \c value.
#define changeBit(word,bit,value) 	((clearBit((word),(bit))) | ((value) << (bit)))

#if 1
// Note: pinMode(), analogWrite() and digitalWrite() should be able to be called from setup()
// Likewise, thread launch should be able to be called from setup()
// Also, make volume change functions callable from render() thread -- as an aux task?

/**
 * \brief Read an analog input, specifying the frame number (when to read) and the channel.
 *
 * This function returns the value of an analog input, at the time indicated by \c frame.
 * The returned value ranges from 0 to 1, corresponding to a voltage range of 0 to 4.096V.
 *
 * \param context The I/O data structure which is passed by BeagleRT to render().
 * \param frame Which frame (i.e. what time) to read the analog input. Valid values range
 * from 0 to (context->analogFrames - 1).
 * \param channel Which analog input to read. Valid values are between 0 and
 * (context->analogChannels - 1), typically 0 to 7 by default.
 * \return Value of the analog input, range 0 to 1.
 */
float analogReadFrame(BeagleRTContext *context, int frame, int channel);

/**
 * \brief Write an analog output, specifying the frame number (when to write) and the channel.
 *
 * This function sets the value of an analog output, at the time indicated by \c frame. Valid
 * values are between 0 and 1, corresponding to the range 0 to 5V.
 *
 * The value written will persist for all future frames if BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST
 * is set in context->flags. This is the default behaviour.
 *
 * \param context The I/O data structure which is passed by BeagleRT to render().
 * \param frame Which frame (i.e. what time) to write the analog output. Valid values range
 * from 0 to (context->analogFrames - 1).
 * \param channel Which analog output to write. Valid values are between 0 and
 * (context->analogChannels - 1), typically 0 to 7 by default.
 * \param value Value to write to the output, range 0 to 1.
 */
void analogWriteFrame(BeagleRTContext *context, int frame, int channel, float value);

/**
 * \brief Write an analog output, specifying the frame number (when to write) and the channel.
 *
 * This function sets the value of an analog output, at the time indicated by \c frame. Valid
 * values are between 0 and 1, corresponding to the range 0 to 5V.
 *
 * Unlike analogWriteFrame(), the value written will affect \b only the frame specified, with
 * future values unchanged. This is more efficient than analogWriteFrame() so is better suited
 * to applications where every frame will be written to a different value. If
 * BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST is not set within context->flags, then
 * analogWriteFrameOnce() and analogWriteFrame() are equivalent.
 *
 * \param context The I/O data structure which is passed by BeagleRT to render().
 * \param frame Which frame (i.e. what time) to write the analog output. Valid values range
 * from 0 to (context->analogFrames - 1).
 * \param channel Which analog output to write. Valid values are between 0 and
 * (context->analogChannels - 1), typically 0 to 7 by default.
 * \param value Value to write to the output, range 0 to 1.
 */
void analogWriteFrameOnce(BeagleRTContext *context, int frame, int channel, float value);

int digitalReadFrame(BeagleRTContext *context, int frame, int channel);
void digitalWriteFrame(BeagleRTContext *context, int frame, int channel, int value);
void digitalWriteFrameOnce(BeagleRTContext *context, int frame, int channel, int value);

void pinModeFrame(BeagleRTContext *context, int frame, int channel, int mode);
void pinModeFrameOnce(BeagleRTContext *context, int frame, int channel, int mode);

#else

// Macros for accessing the analog values: usable _only_ within render()

// Read an Analog input from input pin p at frame f
#define analogRead(p, f) (analogIn[(f)*gNumAnalogChannels + (p)])
// Write an Analog output frame at output pin p, frame f, to value v
#define analogWriteFrame(p, f, v) (analogOut[(f)*gNumAnalogChannels + (p)] = (v))
#define analogWrite(pin, frame, value) \
(({do {\
	for (int _privateI=(frame); _privateI<numAnalogFrames; _privateI++){ \
		analogWriteFrame(pin,_privateI,value); \
	}\
	} while (0);}),(void)0)\


//digital API:
#define setDigitalDirectionFrame(pin,frame,direction) digital[(frame)]=changeBit(digital[(frame)],(pin),(direction)),void(0)
#define setDigitalDirection(pin,frame,direction)\
		(({do {\
			for(int _privateI=(frame); _privateI<numDigitalFrames; _privateI++)\
				setDigitalDirectionFrame(pin,_privateI,direction);\
			} while (0);}), (void)0)
#define digitalWriteAll(frame,value) digital[(frame)]=0xffff0000*(!(!value));
//sets the bit in the high word, clears the bit in the low word (just in case the direction was not previously set)
#define digitalWriteFrame(pin, frame, value) digital[(frame)]=( changeBit(digital[(frame)], (pin+16), (value)) & (0xffffffff-(1<<(pin))) ) //could have been done with two subsequent assignments
#define digitalWrite(pin, frame, value) \
	(({do {\
		for (int _privateI=(frame); _privateI<numDigitalFrames; _privateI++) \
			digitalWriteFrame(pin,_privateI,value); \
		} while (0);}),(void)0)\

#define digitalRead(pin, frame) ( getBit(digital[(frame)], pin+16) )

#endif

/**
 * \brief Linearly rescale a number from one range of values to another.
 *
 * This function linearly scales values of \c x such that the range in_min to
 * in_max at the input corresponds to the range out_min to out_max
 * at the output. Values outside this range are extrapolated.
 *
 * This function behaves identically to the function of the same name in Processing. It
 * is also similar to the corresponding function in Arduino, except that it supports floating
 * point values.
 *
 * \param x Input value to be mapped.
 * \param in_min Lower bound of the input range.
 * \param in_max Upper bound of the input range.
 * \param out_min Lower bound of the output range.
 * \param out_max Upper bound of the output range.
 * \return Rescaled value.
 */
float map(float x, float in_min, float in_max, float out_min, float out_max);

/**
 * \brief Constrain a number to stay within a given range.
 *
 * This function constrains \c x to remain within the range min_val to
 * max_val. Values of \c x outside this range are clipped to the edges
 * of the range.
 *
 * This function behaves identically to the function of the same name in Processing. It
 * is also similar to the corresponding function in Arduino, except that it supports floating
 * point values.
 *
 * \param x Input value to be constrained.
 * \param min_val Minimum possible value.
 * \param max_val Maximum possible value.
 * \return Constrained value.
 */
float constrain(float x, float min_val, float max_val);

#endif /* UTILITIES_H_ */