| andrewm@66 | 1 /** | 
| andrewm@66 | 2  *  @file | 
| andrewm@66 | 3  *  @brief Wiring-inspired utility functions and macros | 
| andrewm@0 | 4  * | 
| andrewm@66 | 5  *  Macros and functions for I/O and data processing taking after the Wiring | 
| andrewm@66 | 6  *  (Arduino) language. This code began as part of the Hackable Instruments | 
| andrewm@66 | 7  *  project (EPSRC) at Queen Mary University of London, 2013-14. | 
| andrewm@66 | 8  * | 
| andrewm@66 | 9  *  (c) 2014-15 Andrew McPherson, Victor Zappi and Giulio Moro, | 
| andrewm@66 | 10  *  Queen Mary University of London | 
| andrewm@0 | 11  */ | 
| andrewm@0 | 12 | 
| andrewm@0 | 13 #ifndef UTILITIES_H_ | 
| andrewm@0 | 14 #define UTILITIES_H_ | 
| andrewm@0 | 15 | 
| giuliomoro@301 | 16 #include "Bela.h" | 
| andrewm@45 | 17 | 
| andrewm@95 | 18 /** | 
| andrewm@95 | 19  * \defgroup iofunctions I/O functions and constants | 
| andrewm@95 | 20  * | 
| andrewm@95 | 21  * These functions and macros are used for audio, analog and digital I/O. All the | 
| giuliomoro@301 | 22  * I/O functions require the BelaContext data structure from render() to be passed | 
| andrewm@95 | 23  * in. This means that these functions are, by design, \b only usable from within | 
| andrewm@95 | 24  * the rendering thread. | 
| andrewm@95 | 25  * | 
| andrewm@95 | 26  * The naming conventions are loosely derived from the Arduino environment, and the | 
| andrewm@95 | 27  * syntax is similar. Unlike Arduino, the I/O functions require the frame number at which | 
| andrewm@95 | 28  * the read or write should take place, since all I/O happens synchronously with the | 
| andrewm@95 | 29  * audio clock. | 
| andrewm@95 | 30  * | 
| andrewm@95 | 31  * @{ | 
| andrewm@95 | 32  */ | 
| andrewm@95 | 33 | 
| giuliomoro@187 | 34 #ifndef INPUT | 
| giuliomoro@187 | 35 	#define INPUT 0x0 | 
| giuliomoro@187 | 36 #endif /* INPUT */ | 
| andrewm@72 | 37 | 
| giuliomoro@187 | 38 #ifndef OUTPUT | 
| giuliomoro@187 | 39 	#define OUTPUT 0x1 | 
| giuliomoro@187 | 40 #endif /* OUTPUT */ | 
| andrewm@72 | 41 | 
| andrewm@95 | 42 /** @} */ | 
| andrewm@95 | 43 | 
| andrewm@95 | 44 /** | 
| andrewm@95 | 45  * \ingroup wiring | 
| andrewm@95 | 46  * | 
| andrewm@95 | 47  * @{ | 
| andrewm@95 | 48  */ | 
| andrewm@95 | 49 | 
| andrewm@66 | 50 /// Set the given bit in \c word to 1. | 
| andrewm@45 | 51 #define setBit(word,bit) 			((word) | (1 << (bit))) | 
| andrewm@66 | 52 | 
| andrewm@66 | 53 /// Clear the given bit in \c word to 0. | 
| andrewm@45 | 54 #define clearBit(word,bit) 			((word) &~ (1 << (bit))) | 
| andrewm@66 | 55 | 
| andrewm@66 | 56 /// Check if the given bit in \c word is 1 (returns nonzero) or 0 (returns zero). | 
| andrewm@45 | 57 #define getBit(word,bit) 			(((word) >> (bit)) & 1) | 
| andrewm@66 | 58 | 
| andrewm@66 | 59 /// Set/clear the given bit in \c word to \c value. | 
| andrewm@45 | 60 #define changeBit(word,bit,value) 	((clearBit((word),(bit))) | ((value) << (bit))) | 
| andrewm@45 | 61 | 
| andrewm@95 | 62 /** @} */ | 
| andrewm@95 | 63 | 
| andrewm@95 | 64 /** | 
| andrewm@95 | 65  * \ingroup iofunctions | 
| andrewm@95 | 66  * | 
| andrewm@95 | 67  * @{ | 
| andrewm@95 | 68  */ | 
| andrewm@95 | 69 | 
| andrewm@56 | 70 // Note: pinMode(), analogWrite() and digitalWrite() should be able to be called from setup() | 
| andrewm@56 | 71 // Likewise, thread launch should be able to be called from setup() | 
| andrewm@45 | 72 // Also, make volume change functions callable from render() thread -- as an aux task? | 
| andrewm@45 | 73 | 
| andrewm@68 | 74 /** | 
| giuliomoro@179 | 75  * \brief Read an audio input, specifying the frame number (when to read) and the channel. | 
| giuliomoro@179 | 76  * | 
| giuliomoro@179 | 77  * This function returns the value of an audio input, at the time indicated by \c frame. | 
| giuliomoro@179 | 78  * The returned value ranges from -1 to 1. | 
| giuliomoro@179 | 79  * | 
| giuliomoro@301 | 80  * \param context The I/O data structure which is passed by Bela to render(). | 
| giuliomoro@179 | 81  * \param frame Which frame (i.e. what time) to read the audio input. Valid values range | 
| giuliomoro@179 | 82  * from 0 to (context->audioFrames - 1). | 
| giuliomoro@179 | 83  * \param channel Which audio input to read. Valid values are between 0 and | 
| giuliomoro@179 | 84  * (context->audioChannels - 1), typically 0 to 1 by default. | 
| giuliomoro@179 | 85  * \return Value of the analog input, range  to 1. | 
| giuliomoro@179 | 86  */ | 
| andrewm@308 | 87 static inline float audioRead(BelaContext *context, int frame, int channel); | 
| giuliomoro@179 | 88 | 
| giuliomoro@179 | 89 /** | 
| giuliomoro@179 | 90  * \brief Write an audio output, specifying the frame number (when to write) and the channel. | 
| giuliomoro@179 | 91  * | 
| giuliomoro@179 | 92  * This function sets the value of an audio output, at the time indicated by \c frame. Valid | 
| giuliomoro@179 | 93  * values are between -1 and 1. | 
| giuliomoro@179 | 94  * | 
| giuliomoro@301 | 95  * \param context The I/O data structure which is passed by Bela to render(). | 
| giuliomoro@179 | 96  * \param frame Which frame (i.e. what time) to write the audio output. Valid values range | 
| giuliomoro@179 | 97  * from 0 to (context->audioFrames - 1). | 
| giuliomoro@179 | 98  * \param channel Which analog output to write. Valid values are between 0 and | 
| giuliomoro@179 | 99  * (context->audioChannels - 1), typically 0 to 1 by default. | 
| giuliomoro@179 | 100  * \param value Value to write to the output, range -1 to 1. | 
| giuliomoro@179 | 101  */ | 
| andrewm@308 | 102 static inline void audioWrite(BelaContext *context, int frame, int channel, float value); | 
| giuliomoro@179 | 103 | 
| giuliomoro@179 | 104 /** | 
| andrewm@68 | 105  * \brief Read an analog input, specifying the frame number (when to read) and the channel. | 
| andrewm@68 | 106  * | 
| andrewm@68 | 107  * This function returns the value of an analog input, at the time indicated by \c frame. | 
| andrewm@68 | 108  * The returned value ranges from 0 to 1, corresponding to a voltage range of 0 to 4.096V. | 
| andrewm@68 | 109  * | 
| giuliomoro@301 | 110  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@68 | 111  * \param frame Which frame (i.e. what time) to read the analog input. Valid values range | 
| andrewm@68 | 112  * from 0 to (context->analogFrames - 1). | 
| andrewm@68 | 113  * \param channel Which analog input to read. Valid values are between 0 and | 
| andrewm@68 | 114  * (context->analogChannels - 1), typically 0 to 7 by default. | 
| andrewm@68 | 115  * \return Value of the analog input, range 0 to 1. | 
| andrewm@68 | 116  */ | 
| andrewm@308 | 117 static inline float analogRead(BelaContext *context, int frame, int channel); | 
| andrewm@68 | 118 | 
| andrewm@68 | 119 /** | 
| andrewm@68 | 120  * \brief Write an analog output, specifying the frame number (when to write) and the channel. | 
| andrewm@68 | 121  * | 
| andrewm@68 | 122  * This function sets the value of an analog output, at the time indicated by \c frame. Valid | 
| andrewm@68 | 123  * values are between 0 and 1, corresponding to the range 0 to 5V. | 
| andrewm@68 | 124  * | 
| andrewm@303 | 125  * The value written will persist for all future frames if BELA_FLAG_ANALOG_OUTPUTS_PERSIST | 
| andrewm@68 | 126  * is set in context->flags. This is the default behaviour. | 
| andrewm@68 | 127  * | 
| giuliomoro@301 | 128  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@68 | 129  * \param frame Which frame (i.e. what time) to write the analog output. Valid values range | 
| andrewm@68 | 130  * from 0 to (context->analogFrames - 1). | 
| andrewm@68 | 131  * \param channel Which analog output to write. Valid values are between 0 and | 
| andrewm@68 | 132  * (context->analogChannels - 1), typically 0 to 7 by default. | 
| andrewm@68 | 133  * \param value Value to write to the output, range 0 to 1. | 
| andrewm@68 | 134  */ | 
| andrewm@308 | 135 static inline void analogWrite(BelaContext *context, int frame, int channel, float value); | 
| andrewm@68 | 136 | 
| andrewm@68 | 137 /** | 
| andrewm@68 | 138  * \brief Write an analog output, specifying the frame number (when to write) and the channel. | 
| andrewm@68 | 139  * | 
| andrewm@68 | 140  * This function sets the value of an analog output, at the time indicated by \c frame. Valid | 
| andrewm@68 | 141  * values are between 0 and 1, corresponding to the range 0 to 5V. | 
| andrewm@68 | 142  * | 
| andrewm@308 | 143  * Unlike analogWrite(), the value written will affect \b only the frame specified, with | 
| andrewm@308 | 144  * future values unchanged. This is faster than analogWrite() so is better suited | 
| andrewm@68 | 145  * to applications where every frame will be written to a different value. If | 
| andrewm@303 | 146  * BELA_FLAG_ANALOG_OUTPUTS_PERSIST is not set within context->flags, then | 
| andrewm@308 | 147  * analogWriteOnce() and analogWrite() are equivalent. | 
| andrewm@68 | 148  * | 
| giuliomoro@301 | 149  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@68 | 150  * \param frame Which frame (i.e. what time) to write the analog output. Valid values range | 
| andrewm@68 | 151  * from 0 to (context->analogFrames - 1). | 
| andrewm@68 | 152  * \param channel Which analog output to write. Valid values are between 0 and | 
| andrewm@68 | 153  * (context->analogChannels - 1), typically 0 to 7 by default. | 
| andrewm@68 | 154  * \param value Value to write to the output, range 0 to 1. | 
| andrewm@68 | 155  */ | 
| andrewm@308 | 156 static inline void analogWriteOnce(BelaContext *context, int frame, int channel, float value); | 
| andrewm@45 | 157 | 
| andrewm@72 | 158 /** | 
| andrewm@72 | 159  * \brief Read a digital input, specifying the frame number (when to read) and the pin. | 
| andrewm@72 | 160  * | 
| andrewm@72 | 161  * This function returns the value of a digital input, at the time indicated by \c frame. | 
| andrewm@72 | 162  * The value is 0 if the pin is low, and nonzero if the pin is high (3.3V). | 
| andrewm@72 | 163  * | 
| giuliomoro@301 | 164  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@72 | 165  * \param frame Which frame (i.e. what time) to read the digital input. Valid values range | 
| andrewm@72 | 166  * from 0 to (context->digitalFrames - 1). | 
| andrewm@72 | 167  * \param channel Which digital pin to read. 16 pins across the P8 and P9 headers of the | 
| andrewm@72 | 168  * BeagleBone Black are available. See the constants P8_xx and P9_xx defined in | 
| andrewm@72 | 169  * digital_gpio_mapping.h. | 
| andrewm@72 | 170  * \return Value of the digital input. | 
| andrewm@72 | 171  */ | 
| andrewm@308 | 172 static inline int digitalRead(BelaContext *context, int frame, int channel); | 
| andrewm@72 | 173 | 
| andrewm@72 | 174 /** | 
| andrewm@72 | 175  * \brief Write a digital output, specifying the frame number (when to write) and the pin. | 
| andrewm@72 | 176  * | 
| andrewm@72 | 177  * This function sets the value of a digital output, at the time indicated by \c frame. | 
| andrewm@72 | 178  * A value of 0 sets the pin low; any other value sets the pin high (3.3V). | 
| andrewm@72 | 179  * | 
| andrewm@72 | 180  * The value written will persist for all future frames. | 
| andrewm@72 | 181  * | 
| giuliomoro@301 | 182  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@72 | 183  * \param frame Which frame (i.e. what time) to write the digital output. Valid values range | 
| andrewm@72 | 184  * from 0 to (context->digitalFrames - 1). | 
| andrewm@72 | 185  * \param channel Which digital output to write. 16 pins across the P8 and P9 headers of the | 
| andrewm@72 | 186  * BeagleBone Black are available. See the constants P8_xx and P9_xx defined in | 
| andrewm@72 | 187  * digital_gpio_mapping.h. | 
| andrewm@72 | 188  * \param value Value to write to the output. | 
| andrewm@72 | 189  */ | 
| andrewm@308 | 190 static inline void digitalWrite(BelaContext *context, int frame, int channel, int value); | 
| andrewm@72 | 191 | 
| andrewm@72 | 192 /** | 
| andrewm@72 | 193  * \brief Write a digital output, specifying the frame number (when to write) and the pin. | 
| andrewm@72 | 194  * | 
| andrewm@72 | 195  * This function sets the value of a digital output, at the time indicated by \c frame. | 
| andrewm@72 | 196  * A value of 0 sets the pin low; any other value sets the pin high (3.3V). | 
| andrewm@72 | 197  * | 
| andrewm@308 | 198  * Unlike digitalWrite(), the value written will affect \b only the frame specified, with | 
| andrewm@308 | 199  * future values unchanged. This is faster than digitalWrite() so is better suited | 
| andrewm@72 | 200  * to applications where every frame will be written to a different value. | 
| andrewm@72 | 201  * | 
| giuliomoro@301 | 202  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@72 | 203  * \param frame Which frame (i.e. what time) to write the digital output. Valid values range | 
| andrewm@72 | 204  * from 0 to (context->digitalFrames - 1). | 
| andrewm@72 | 205  * \param channel Which digital output to write. 16 pins across the P8 and P9 headers of the | 
| andrewm@72 | 206  * BeagleBone Black are available. See the constants P8_xx and P9_xx defined in | 
| andrewm@72 | 207  * digital_gpio_mapping.h. | 
| andrewm@72 | 208  * \param value Value to write to the output. | 
| andrewm@72 | 209  */ | 
| andrewm@308 | 210 static inline void digitalWriteOnce(BelaContext *context, int frame, int channel, int value); | 
| andrewm@45 | 211 | 
| andrewm@72 | 212 /** | 
| andrewm@72 | 213  * \brief Set the direction of a digital pin to input or output. | 
| andrewm@72 | 214  * | 
| andrewm@72 | 215  * This function sets the direction of a digital pin, at the time indicated by \c frame. | 
| andrewm@72 | 216  * Valid values are \c INPUT and \c OUTPUT. All pins begin as inputs by default. | 
| andrewm@72 | 217  * | 
| andrewm@72 | 218  * The value written will persist for all future frames. | 
| andrewm@72 | 219  * | 
| giuliomoro@301 | 220  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@72 | 221  * \param frame Which frame (i.e. what time) to set the pin direction. Valid values range | 
| andrewm@72 | 222  * from 0 to (context->digitalFrames - 1). | 
| andrewm@72 | 223  * \param channel Which digital output to write. 16 pins across the P8 and P9 headers of the | 
| andrewm@72 | 224  * BeagleBone Black are available. See the constants P8_xx and P9_xx defined in | 
| andrewm@72 | 225  * digital_gpio_mapping.h. | 
| andrewm@72 | 226  * \param value Direction of the pin (\c INPUT or \c OUTPUT). | 
| andrewm@72 | 227  */ | 
| andrewm@310 | 228 static inline void pinMode(BelaContext *context, int frame, int channel, int mode); | 
| andrewm@72 | 229 | 
| andrewm@72 | 230 /** | 
| andrewm@72 | 231  * \brief Set the direction of a digital pin to input or output. | 
| andrewm@72 | 232  * | 
| andrewm@72 | 233  * This function sets the direction of a digital pin, at the time indicated by \c frame. | 
| andrewm@72 | 234  * Valid values are \c INPUT and \c OUTPUT. All pins begin as inputs by default. | 
| andrewm@72 | 235  * | 
| andrewm@72 | 236  * The value written will affect only the specified frame. | 
| andrewm@72 | 237  * | 
| giuliomoro@301 | 238  * \param context The I/O data structure which is passed by Bela to render(). | 
| andrewm@72 | 239  * \param frame Which frame (i.e. what time) to set the pin direction. Valid values range | 
| andrewm@72 | 240  * from 0 to (context->digitalFrames - 1). | 
| andrewm@72 | 241  * \param channel Which digital output to write. 16 pins across the P8 and P9 headers of the | 
| andrewm@72 | 242  * BeagleBone Black are available. See the constants P8_xx and P9_xx defined in | 
| andrewm@72 | 243  * digital_gpio_mapping.h. | 
| andrewm@72 | 244  * \param value Direction of the pin (\c INPUT or \c OUTPUT). | 
| andrewm@72 | 245  */ | 
| andrewm@310 | 246 static inline void pinModeOnce(BelaContext *context, int frame, int channel, int mode); | 
| andrewm@45 | 247 | 
| andrewm@95 | 248 /** @} */ | 
| andrewm@95 | 249 | 
| andrewm@66 | 250 /** | 
| andrewm@95 | 251  * \defgroup wiring Wiring language support | 
| andrewm@95 | 252  * | 
| andrewm@95 | 253  * These are functions found in the Wiring (Arduino) language which are not directly | 
| andrewm@95 | 254  * related to I/O but are provided as a convenience. | 
| andrewm@95 | 255  * | 
| andrewm@95 | 256  * @{ | 
| andrewm@95 | 257  */ | 
| andrewm@95 | 258 | 
| andrewm@95 | 259 /** | 
| andrewm@66 | 260  * \brief Linearly rescale a number from one range of values to another. | 
| andrewm@66 | 261  * | 
| andrewm@66 | 262  * This function linearly scales values of \c x such that the range in_min to | 
| andrewm@66 | 263  * in_max at the input corresponds to the range out_min to out_max | 
| andrewm@66 | 264  * at the output. Values outside this range are extrapolated. | 
| andrewm@66 | 265  * | 
| andrewm@66 | 266  * This function behaves identically to the function of the same name in Processing. It | 
| andrewm@66 | 267  * is also similar to the corresponding function in Arduino, except that it supports floating | 
| andrewm@66 | 268  * point values. | 
| andrewm@66 | 269  * | 
| andrewm@66 | 270  * \param x Input value to be mapped. | 
| andrewm@66 | 271  * \param in_min Lower bound of the input range. | 
| andrewm@66 | 272  * \param in_max Upper bound of the input range. | 
| andrewm@66 | 273  * \param out_min Lower bound of the output range. | 
| andrewm@66 | 274  * \param out_max Upper bound of the output range. | 
| andrewm@66 | 275  * \return Rescaled value. | 
| andrewm@66 | 276  */ | 
| giuliomoro@187 | 277 static inline float map(float x, float in_min, float in_max, float out_min, float out_max); | 
| andrewm@66 | 278 | 
| andrewm@66 | 279 /** | 
| andrewm@66 | 280  * \brief Constrain a number to stay within a given range. | 
| andrewm@66 | 281  * | 
| andrewm@66 | 282  * This function constrains \c x to remain within the range min_val to | 
| andrewm@66 | 283  * max_val. Values of \c x outside this range are clipped to the edges | 
| andrewm@66 | 284  * of the range. | 
| andrewm@66 | 285  * | 
| andrewm@66 | 286  * This function behaves identically to the function of the same name in Processing. It | 
| andrewm@66 | 287  * is also similar to the corresponding function in Arduino, except that it supports floating | 
| andrewm@66 | 288  * point values. | 
| andrewm@66 | 289  * | 
| andrewm@66 | 290  * \param x Input value to be constrained. | 
| andrewm@66 | 291  * \param min_val Minimum possible value. | 
| andrewm@66 | 292  * \param max_val Maximum possible value. | 
| andrewm@66 | 293  * \return Constrained value. | 
| andrewm@66 | 294  */ | 
| giuliomoro@187 | 295 static inline float constrain(float x, float min_val, float max_val); | 
| andrewm@0 | 296 | 
| andrewm@95 | 297 /** @} */ | 
| andrewm@308 | 298 // audioRead() | 
| giuliomoro@187 | 299 // | 
| giuliomoro@187 | 300 // Returns the value of the given audio input at the given frame number. | 
| andrewm@308 | 301 static inline float audioRead(BelaContext *context, int frame, int channel) { | 
| giuliomoro@187 | 302 	return context->audioIn[frame * context->audioChannels + channel]; | 
| giuliomoro@187 | 303 } | 
| giuliomoro@187 | 304 | 
| andrewm@308 | 305 // audioWrite() | 
| giuliomoro@187 | 306 // | 
| giuliomoro@187 | 307 // Sets a given audio output channel to a value for the current frame | 
| andrewm@308 | 308 static inline void audioWrite(BelaContext *context, int frame, int channel, float value) { | 
| giuliomoro@187 | 309 	context->audioOut[frame * context->audioChannels + channel] = value; | 
| giuliomoro@187 | 310 } | 
| giuliomoro@187 | 311 | 
| andrewm@308 | 312 // analogRead() | 
| giuliomoro@187 | 313 // | 
| giuliomoro@187 | 314 // Returns the value of the given analog input at the given frame number. | 
| andrewm@308 | 315 static inline float analogRead(BelaContext *context, int frame, int channel) { | 
| giuliomoro@187 | 316 	return context->analogIn[frame * context->analogChannels + channel]; | 
| giuliomoro@187 | 317 } | 
| giuliomoro@187 | 318 | 
| andrewm@308 | 319 // analogWrite() | 
| giuliomoro@187 | 320 // | 
| giuliomoro@187 | 321 // Sets a given analog output channel to a value for the current frame and, if persistent outputs are | 
| giuliomoro@187 | 322 // enabled, for all subsequent frames | 
| andrewm@308 | 323 static inline void analogWrite(BelaContext *context, int frame, int channel, float value) { | 
| andrewm@303 | 324 	if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { | 
| giuliomoro@187 | 325 		for(unsigned int f = frame; f < context->analogFrames; f++) | 
| giuliomoro@187 | 326 			context->analogOut[frame * context->analogChannels + channel] = value; | 
| giuliomoro@187 | 327 	} | 
| giuliomoro@187 | 328 	else | 
| giuliomoro@187 | 329 		context->analogOut[frame * context->analogChannels + channel] = value; | 
| giuliomoro@187 | 330 } | 
| giuliomoro@187 | 331 | 
| andrewm@308 | 332 // analogWriteOnce() | 
| giuliomoro@187 | 333 // | 
| giuliomoro@187 | 334 // Sets a given channel to a value for only the current frame | 
| andrewm@308 | 335 static inline void analogWriteOnce(BelaContext *context, int frame, int channel, float value) { | 
| giuliomoro@187 | 336 	context->analogOut[frame * context->analogChannels + channel] = value; | 
| giuliomoro@187 | 337 } | 
| giuliomoro@187 | 338 | 
| andrewm@308 | 339 // digitalRead() | 
| giuliomoro@187 | 340 // | 
| giuliomoro@187 | 341 // Returns the value of a given digital input at the given frame number | 
| andrewm@308 | 342 static inline int digitalRead(BelaContext *context, int frame, int channel) { | 
| giuliomoro@187 | 343 	return getBit(context->digital[frame], channel + 16); | 
| giuliomoro@187 | 344 } | 
| giuliomoro@187 | 345 | 
| andrewm@308 | 346 // digitalWrite() | 
| giuliomoro@187 | 347 // | 
| giuliomoro@187 | 348 // Sets a given digital output channel to a value for the current frame and all subsequent frames | 
| andrewm@308 | 349 static inline void digitalWrite(BelaContext *context, int frame, int channel, int value) { | 
| giuliomoro@187 | 350 	for(unsigned int f = frame; f < context->digitalFrames; f++) { | 
| giuliomoro@187 | 351 		if(value) | 
| giuliomoro@187 | 352 			context->digital[f] |= 1 << (channel + 16); | 
| giuliomoro@187 | 353 		else | 
| giuliomoro@187 | 354 			context->digital[f] &= ~(1 << (channel + 16)); | 
| giuliomoro@187 | 355 	} | 
| giuliomoro@187 | 356 } | 
| giuliomoro@187 | 357 | 
| andrewm@308 | 358 // digitalWriteOnce() | 
| giuliomoro@187 | 359 // | 
| giuliomoro@187 | 360 // Sets a given digital output channel to a value for the current frame only | 
| andrewm@308 | 361 static inline void digitalWriteOnce(BelaContext *context, int frame, int channel, int value) { | 
| giuliomoro@187 | 362 	if(value) | 
| giuliomoro@187 | 363 		context->digital[frame] |= 1 << (channel + 16); | 
| giuliomoro@187 | 364 	else | 
| giuliomoro@187 | 365 		context->digital[frame] &= ~(1 << (channel + 16)); | 
| giuliomoro@187 | 366 } | 
| giuliomoro@187 | 367 | 
| andrewm@310 | 368 // pinMode() | 
| giuliomoro@187 | 369 // | 
| giuliomoro@187 | 370 // Sets the direction of a digital pin for the current frame and all subsequent frames | 
| andrewm@310 | 371 static inline void pinMode(BelaContext *context, int frame, int channel, int mode) { | 
| giuliomoro@187 | 372 	for(unsigned int f = frame; f < context->digitalFrames; f++) { | 
| giuliomoro@187 | 373 		if(mode == INPUT) | 
| giuliomoro@187 | 374 			context->digital[f] |= (1 << channel); | 
| giuliomoro@187 | 375 		else | 
| giuliomoro@187 | 376 			context->digital[f] &= ~(1 << channel); | 
| giuliomoro@187 | 377 	} | 
| giuliomoro@187 | 378 } | 
| giuliomoro@187 | 379 | 
| andrewm@310 | 380 // pinModeOnce() | 
| giuliomoro@187 | 381 // | 
| giuliomoro@187 | 382 // Sets the direction of a digital pin for the current frame only | 
| andrewm@310 | 383 static inline void pinModeOnce(BelaContext *context, int frame, int channel, int mode) { | 
| giuliomoro@187 | 384 	if(mode == INPUT) | 
| giuliomoro@187 | 385 		context->digital[frame] |= (1 << channel); | 
| giuliomoro@187 | 386 	else | 
| giuliomoro@187 | 387 		context->digital[frame] &= ~(1 << channel); | 
| giuliomoro@187 | 388 } | 
| giuliomoro@187 | 389 | 
| giuliomoro@187 | 390 | 
| giuliomoro@187 | 391 | 
| giuliomoro@187 | 392 // map() | 
| giuliomoro@187 | 393 // | 
| giuliomoro@187 | 394 // Scale an input value from one range to another. Works like its Wiring language equivalent. | 
| giuliomoro@187 | 395 // x is the value to scale; in_min and in_max are the input range; out_min and out_max | 
| giuliomoro@187 | 396 // are the output range. | 
| giuliomoro@187 | 397 | 
| giuliomoro@187 | 398 static inline float map(float x, float in_min, float in_max, float out_min, float out_max) | 
| giuliomoro@187 | 399 { | 
| giuliomoro@187 | 400 	return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | 
| giuliomoro@187 | 401 } | 
| giuliomoro@187 | 402 | 
| giuliomoro@187 | 403 // constrain() | 
| giuliomoro@187 | 404 // | 
| giuliomoro@187 | 405 // Clips an input value to be between two end points | 
| giuliomoro@187 | 406 // x is the value to constrain; min_val and max_val are the range | 
| giuliomoro@187 | 407 | 
| giuliomoro@187 | 408 static inline float constrain(float x, float min_val, float max_val) | 
| giuliomoro@187 | 409 { | 
| giuliomoro@187 | 410 	if(x < min_val) return min_val; | 
| giuliomoro@187 | 411 	if(x > max_val) return max_val; | 
| giuliomoro@187 | 412 	return x; | 
| giuliomoro@187 | 413 } | 
| andrewm@95 | 414 | 
| andrewm@0 | 415 #endif /* UTILITIES_H_ */ |