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
|
andrewm@45
|
16 #include "BeagleRT.h"
|
andrewm@45
|
17
|
andrewm@66
|
18 /// Set the given bit in \c word to 1.
|
andrewm@45
|
19 #define setBit(word,bit) ((word) | (1 << (bit)))
|
andrewm@66
|
20
|
andrewm@66
|
21 /// Clear the given bit in \c word to 0.
|
andrewm@45
|
22 #define clearBit(word,bit) ((word) &~ (1 << (bit)))
|
andrewm@66
|
23
|
andrewm@66
|
24 /// Check if the given bit in \c word is 1 (returns nonzero) or 0 (returns zero).
|
andrewm@45
|
25 #define getBit(word,bit) (((word) >> (bit)) & 1)
|
andrewm@66
|
26
|
andrewm@66
|
27 /// Set/clear the given bit in \c word to \c value.
|
andrewm@45
|
28 #define changeBit(word,bit,value) ((clearBit((word),(bit))) | ((value) << (bit)))
|
andrewm@45
|
29
|
andrewm@45
|
30 #if 1
|
andrewm@56
|
31 // Note: pinMode(), analogWrite() and digitalWrite() should be able to be called from setup()
|
andrewm@56
|
32 // Likewise, thread launch should be able to be called from setup()
|
andrewm@45
|
33 // Also, make volume change functions callable from render() thread -- as an aux task?
|
andrewm@45
|
34
|
andrewm@45
|
35 float analogReadFrame(BeagleRTContext *context, int frame, int channel);
|
andrewm@45
|
36 void analogWriteFrame(BeagleRTContext *context, int frame, int channel, float value);
|
andrewm@45
|
37 void analogWriteFrameOnce(BeagleRTContext *context, int frame, int channel, float value);
|
andrewm@45
|
38
|
andrewm@45
|
39 int digitalReadFrame(BeagleRTContext *context, int frame, int channel);
|
andrewm@45
|
40 void digitalWriteFrame(BeagleRTContext *context, int frame, int channel, int value);
|
andrewm@45
|
41 void digitalWriteFrameOnce(BeagleRTContext *context, int frame, int channel, int value);
|
andrewm@45
|
42
|
andrewm@45
|
43 void pinModeFrame(BeagleRTContext *context, int frame, int channel, int mode);
|
andrewm@45
|
44 void pinModeFrameOnce(BeagleRTContext *context, int frame, int channel, int mode);
|
andrewm@45
|
45
|
andrewm@45
|
46 #else
|
andrewm@13
|
47
|
giuliomoro@19
|
48 // Macros for accessing the analog values: usable _only_ within render()
|
andrewm@5
|
49
|
giuliomoro@19
|
50 // Read an Analog input from input pin p at frame f
|
giuliomoro@23
|
51 #define analogRead(p, f) (analogIn[(f)*gNumAnalogChannels + (p)])
|
giuliomoro@19
|
52 // Write an Analog output frame at output pin p, frame f, to value v
|
giuliomoro@23
|
53 #define analogWriteFrame(p, f, v) (analogOut[(f)*gNumAnalogChannels + (p)] = (v))
|
giuliomoro@23
|
54 #define analogWrite(pin, frame, value) \
|
giuliomoro@18
|
55 (({do {\
|
giuliomoro@19
|
56 for (int _privateI=(frame); _privateI<numAnalogFrames; _privateI++){ \
|
giuliomoro@23
|
57 analogWriteFrame(pin,_privateI,value); \
|
giuliomoro@18
|
58 }\
|
giuliomoro@18
|
59 } while (0);}),(void)0)\
|
andrewm@5
|
60
|
andrewm@45
|
61
|
giuliomoro@19
|
62 //digital API:
|
giuliomoro@33
|
63 #define setDigitalDirectionFrame(pin,frame,direction) digital[(frame)]=changeBit(digital[(frame)],(pin),(direction)),void(0)
|
giuliomoro@33
|
64 #define setDigitalDirection(pin,frame,direction)\
|
giuliomoro@33
|
65 (({do {\
|
giuliomoro@33
|
66 for(int _privateI=(frame); _privateI<numDigitalFrames; _privateI++)\
|
giuliomoro@33
|
67 setDigitalDirectionFrame(pin,_privateI,direction);\
|
giuliomoro@33
|
68 } while (0);}), (void)0)
|
giuliomoro@19
|
69 #define digitalWriteAll(frame,value) digital[(frame)]=0xffff0000*(!(!value));
|
giuliomoro@16
|
70 //sets the bit in the high word, clears the bit in the low word (just in case the direction was not previously set)
|
giuliomoro@19
|
71 #define digitalWriteFrame(pin, frame, value) digital[(frame)]=( changeBit(digital[(frame)], (pin+16), (value)) & (0xffffffff-(1<<(pin))) ) //could have been done with two subsequent assignments
|
giuliomoro@18
|
72 #define digitalWrite(pin, frame, value) \
|
giuliomoro@18
|
73 (({do {\
|
giuliomoro@33
|
74 for (int _privateI=(frame); _privateI<numDigitalFrames; _privateI++) \
|
giuliomoro@18
|
75 digitalWriteFrame(pin,_privateI,value); \
|
giuliomoro@18
|
76 } while (0);}),(void)0)\
|
giuliomoro@18
|
77
|
giuliomoro@19
|
78 #define digitalRead(pin, frame) ( getBit(digital[(frame)], pin+16) )
|
giuliomoro@16
|
79
|
andrewm@45
|
80 #endif
|
andrewm@45
|
81
|
andrewm@66
|
82 /**
|
andrewm@66
|
83 * \brief Linearly rescale a number from one range of values to another.
|
andrewm@66
|
84 *
|
andrewm@66
|
85 * This function linearly scales values of \c x such that the range in_min to
|
andrewm@66
|
86 * in_max at the input corresponds to the range out_min to out_max
|
andrewm@66
|
87 * at the output. Values outside this range are extrapolated.
|
andrewm@66
|
88 *
|
andrewm@66
|
89 * This function behaves identically to the function of the same name in Processing. It
|
andrewm@66
|
90 * is also similar to the corresponding function in Arduino, except that it supports floating
|
andrewm@66
|
91 * point values.
|
andrewm@66
|
92 *
|
andrewm@66
|
93 * \param x Input value to be mapped.
|
andrewm@66
|
94 * \param in_min Lower bound of the input range.
|
andrewm@66
|
95 * \param in_max Upper bound of the input range.
|
andrewm@66
|
96 * \param out_min Lower bound of the output range.
|
andrewm@66
|
97 * \param out_max Upper bound of the output range.
|
andrewm@66
|
98 * \return Rescaled value.
|
andrewm@66
|
99 */
|
andrewm@0
|
100 float map(float x, float in_min, float in_max, float out_min, float out_max);
|
andrewm@66
|
101
|
andrewm@66
|
102 /**
|
andrewm@66
|
103 * \brief Constrain a number to stay within a given range.
|
andrewm@66
|
104 *
|
andrewm@66
|
105 * This function constrains \c x to remain within the range min_val to
|
andrewm@66
|
106 * max_val. Values of \c x outside this range are clipped to the edges
|
andrewm@66
|
107 * of the range.
|
andrewm@66
|
108 *
|
andrewm@66
|
109 * This function behaves identically to the function of the same name in Processing. It
|
andrewm@66
|
110 * is also similar to the corresponding function in Arduino, except that it supports floating
|
andrewm@66
|
111 * point values.
|
andrewm@66
|
112 *
|
andrewm@66
|
113 * \param x Input value to be constrained.
|
andrewm@66
|
114 * \param min_val Minimum possible value.
|
andrewm@66
|
115 * \param max_val Maximum possible value.
|
andrewm@66
|
116 * \return Constrained value.
|
andrewm@66
|
117 */
|
andrewm@0
|
118 float constrain(float x, float min_val, float max_val);
|
andrewm@0
|
119
|
andrewm@0
|
120 #endif /* UTILITIES_H_ */
|