I2S driver modified for UDA1345 slave mode
Fork of I2S by
I2S.h@0:455d5826751b, 2012-09-19 (annotated)
- Committer:
- p07gbar
- Date:
- Wed Sep 19 10:53:33 2012 +0000
- Revision:
- 0:455d5826751b
Working fairly stably with read/write 16/32 tx/rx
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
p07gbar | 0:455d5826751b | 1 | /** |
p07gbar | 0:455d5826751b | 2 | * @author Giles Barton-Owen |
p07gbar | 0:455d5826751b | 3 | * |
p07gbar | 0:455d5826751b | 4 | * @section LICENSE |
p07gbar | 0:455d5826751b | 5 | * |
p07gbar | 0:455d5826751b | 6 | * Copyright (c) 2012 mbed |
p07gbar | 0:455d5826751b | 7 | * |
p07gbar | 0:455d5826751b | 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
p07gbar | 0:455d5826751b | 9 | * of this software and associated documentation files (the "Software"), to deal |
p07gbar | 0:455d5826751b | 10 | * in the Software without restriction, including without limitation the rights |
p07gbar | 0:455d5826751b | 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
p07gbar | 0:455d5826751b | 12 | * copies of the Software, and to permit persons to whom the Software is |
p07gbar | 0:455d5826751b | 13 | * furnished to do so, subject to the following conditions: |
p07gbar | 0:455d5826751b | 14 | * |
p07gbar | 0:455d5826751b | 15 | * The above copyright notice and this permission notice shall be included in |
p07gbar | 0:455d5826751b | 16 | * all copies or substantial portions of the Software. |
p07gbar | 0:455d5826751b | 17 | * |
p07gbar | 0:455d5826751b | 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
p07gbar | 0:455d5826751b | 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
p07gbar | 0:455d5826751b | 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
p07gbar | 0:455d5826751b | 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
p07gbar | 0:455d5826751b | 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
p07gbar | 0:455d5826751b | 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
p07gbar | 0:455d5826751b | 24 | * THE SOFTWARE. |
p07gbar | 0:455d5826751b | 25 | * |
p07gbar | 0:455d5826751b | 26 | * @section DESCRIPTION |
p07gbar | 0:455d5826751b | 27 | * A I2S library for the LPC1768's built-in I2S peripheral |
p07gbar | 0:455d5826751b | 28 | * |
p07gbar | 0:455d5826751b | 29 | */ |
p07gbar | 0:455d5826751b | 30 | |
p07gbar | 0:455d5826751b | 31 | #include "mbed.h" |
p07gbar | 0:455d5826751b | 32 | #include "math.h" |
p07gbar | 0:455d5826751b | 33 | |
p07gbar | 0:455d5826751b | 34 | #ifndef I2S_H |
p07gbar | 0:455d5826751b | 35 | #define I2S_H |
p07gbar | 0:455d5826751b | 36 | |
p07gbar | 0:455d5826751b | 37 | #define I2S_TRANSMIT 0 |
p07gbar | 0:455d5826751b | 38 | #define I2S_RECEIVE 1 |
p07gbar | 0:455d5826751b | 39 | |
p07gbar | 0:455d5826751b | 40 | #define I2S_MASTER 0 |
p07gbar | 0:455d5826751b | 41 | #define I2S_SLAVE 1 |
p07gbar | 0:455d5826751b | 42 | |
p07gbar | 0:455d5826751b | 43 | #define I2S_STEREO 0 |
p07gbar | 0:455d5826751b | 44 | #define I2S_MONO 1 |
p07gbar | 0:455d5826751b | 45 | |
p07gbar | 0:455d5826751b | 46 | #define I2S_MUTED 1 |
p07gbar | 0:455d5826751b | 47 | #define I2S_UNMUTED 0 |
p07gbar | 0:455d5826751b | 48 | |
p07gbar | 0:455d5826751b | 49 | #define I2S_4WIRE 1 |
p07gbar | 0:455d5826751b | 50 | #define I2S_3WIRE 0 |
p07gbar | 0:455d5826751b | 51 | |
p07gbar | 0:455d5826751b | 52 | /** A class to play give access to the I2S library |
p07gbar | 0:455d5826751b | 53 | */ |
p07gbar | 0:455d5826751b | 54 | |
p07gbar | 0:455d5826751b | 55 | class I2S |
p07gbar | 0:455d5826751b | 56 | { |
p07gbar | 0:455d5826751b | 57 | |
p07gbar | 0:455d5826751b | 58 | public: |
p07gbar | 0:455d5826751b | 59 | |
p07gbar | 0:455d5826751b | 60 | /** Create a I2S instance |
p07gbar | 0:455d5826751b | 61 | * |
p07gbar | 0:455d5826751b | 62 | * @param rxtx Set the I2S instance to be transmit or recieve (I2S_TRANSMIT/I2S_RECEIVE) |
p07gbar | 0:455d5826751b | 63 | * @param sd The serial data pin |
p07gbar | 0:455d5826751b | 64 | * @param ws The word select pin |
p07gbar | 0:455d5826751b | 65 | * @param clk The clock pin |
p07gbar | 0:455d5826751b | 66 | */ |
p07gbar | 0:455d5826751b | 67 | I2S(bool rxtx, PinName sd, PinName ws, PinName clk); |
p07gbar | 0:455d5826751b | 68 | |
p07gbar | 0:455d5826751b | 69 | /** Create a I2S instance: Only with the serial data line set. Won't really do much. |
p07gbar | 0:455d5826751b | 70 | * |
p07gbar | 0:455d5826751b | 71 | * @param rxtx Set the I2S instance to be transmit or recieve (I2S_TRANSMIT/I2S_RECEIVE) |
p07gbar | 0:455d5826751b | 72 | * @param sd The serial data pin |
p07gbar | 0:455d5826751b | 73 | */ |
p07gbar | 0:455d5826751b | 74 | I2S(bool rxtx, PinName sd); |
p07gbar | 0:455d5826751b | 75 | |
p07gbar | 0:455d5826751b | 76 | |
p07gbar | 0:455d5826751b | 77 | /** Create a I2S instance: Only with serial data line and word select. |
p07gbar | 0:455d5826751b | 78 | * |
p07gbar | 0:455d5826751b | 79 | * @param rxtx Set the I2S instance to be transmit or recieve (I2S_TRANSMIT/I2S_RECEIVE) |
p07gbar | 0:455d5826751b | 80 | * @param sd The serial data pin |
p07gbar | 0:455d5826751b | 81 | * @param ws The word select pin |
p07gbar | 0:455d5826751b | 82 | */ |
p07gbar | 0:455d5826751b | 83 | I2S(bool rxtx, PinName sd, PinName ws); |
p07gbar | 0:455d5826751b | 84 | |
p07gbar | 0:455d5826751b | 85 | |
p07gbar | 0:455d5826751b | 86 | |
p07gbar | 0:455d5826751b | 87 | /** Create a I2S instance: Only with serial data line. Four wire mode means this is functional |
p07gbar | 0:455d5826751b | 88 | * |
p07gbar | 0:455d5826751b | 89 | * @param rxtx Set the I2S instance to be transmit or recieve (I2S_TRANSMIT/I2S_RECEIVE) |
p07gbar | 0:455d5826751b | 90 | * @param sd The serial data pin |
p07gbar | 0:455d5826751b | 91 | * @param fourwiremode True means the peripheral is in 4-wire mode. It borrows WS and CLK from the other half |
p07gbar | 0:455d5826751b | 92 | */ |
p07gbar | 0:455d5826751b | 93 | I2S(bool rxtx, PinName sd, bool fourwiremode); |
p07gbar | 0:455d5826751b | 94 | |
p07gbar | 0:455d5826751b | 95 | /** Create a I2S instance: Only with serial data line and word select line. Four wire mode means this is functional |
p07gbar | 0:455d5826751b | 96 | * |
p07gbar | 0:455d5826751b | 97 | * @param rxtx Set the I2S instance to be transmit or recieve (I2S_TRANSMIT/I2S_RECEIVE) |
p07gbar | 0:455d5826751b | 98 | * @param sd The serial data pin |
p07gbar | 0:455d5826751b | 99 | * @param ws The word select pin |
p07gbar | 0:455d5826751b | 100 | * @param fourwiremode True means the peripheral is in 4-wire mode. It borrows WS and CLK from the other half |
p07gbar | 0:455d5826751b | 101 | */ |
p07gbar | 0:455d5826751b | 102 | I2S(bool rxtx, PinName sd, PinName ws, bool fourwiremode); |
p07gbar | 0:455d5826751b | 103 | |
p07gbar | 0:455d5826751b | 104 | /** Destroy the I2S instance |
p07gbar | 0:455d5826751b | 105 | */ |
p07gbar | 0:455d5826751b | 106 | ~I2S(); |
p07gbar | 0:455d5826751b | 107 | |
p07gbar | 0:455d5826751b | 108 | /** Write to the FIFO |
p07gbar | 0:455d5826751b | 109 | * |
p07gbar | 0:455d5826751b | 110 | * @param buf[] The buffer of values to write: are bit stuffed in fours |
p07gbar | 0:455d5826751b | 111 | * @param len The number of chars to write |
p07gbar | 0:455d5826751b | 112 | */ |
p07gbar | 0:455d5826751b | 113 | void write(char buf[], int len); |
p07gbar | 0:455d5826751b | 114 | |
p07gbar | 0:455d5826751b | 115 | /** Write to the FIFO |
p07gbar | 0:455d5826751b | 116 | * |
p07gbar | 0:455d5826751b | 117 | * @param buf[] The buffer of values to write: are bit stuffed automatically |
p07gbar | 0:455d5826751b | 118 | * @param len The number of chars to write |
p07gbar | 0:455d5826751b | 119 | */ |
p07gbar | 0:455d5826751b | 120 | void write(int buf[], int len); |
p07gbar | 0:455d5826751b | 121 | |
p07gbar | 0:455d5826751b | 122 | /** Read the FIFOs contents |
p07gbar | 0:455d5826751b | 123 | * |
p07gbar | 0:455d5826751b | 124 | * @return The buffers value. |
p07gbar | 0:455d5826751b | 125 | */ |
p07gbar | 0:455d5826751b | 126 | int read(); |
p07gbar | 0:455d5826751b | 127 | |
p07gbar | 0:455d5826751b | 128 | /** Read from the FIFO |
p07gbar | 0:455d5826751b | 129 | * |
p07gbar | 0:455d5826751b | 130 | * @param buf[] The buffer of values to read: raw bit shifted |
p07gbar | 0:455d5826751b | 131 | * @param len The number of chars to read |
p07gbar | 0:455d5826751b | 132 | */ |
p07gbar | 0:455d5826751b | 133 | void read(char buf[], int len); |
p07gbar | 0:455d5826751b | 134 | |
p07gbar | 0:455d5826751b | 135 | /** Read from the FIFO |
p07gbar | 0:455d5826751b | 136 | * |
p07gbar | 0:455d5826751b | 137 | * @param buf[] The buffer of values to read: sorted to just values |
p07gbar | 0:455d5826751b | 138 | * @param len The number of chars to read |
p07gbar | 0:455d5826751b | 139 | */ |
p07gbar | 0:455d5826751b | 140 | void read(int buf[], int len); |
p07gbar | 0:455d5826751b | 141 | |
p07gbar | 0:455d5826751b | 142 | /** Get the maximum number of points of data the FIFO could store |
p07gbar | 0:455d5826751b | 143 | * |
p07gbar | 0:455d5826751b | 144 | * @return The number of points |
p07gbar | 0:455d5826751b | 145 | */ |
p07gbar | 0:455d5826751b | 146 | int max_fifo_points(); |
p07gbar | 0:455d5826751b | 147 | /** Switch the peripheral on and off |
p07gbar | 0:455d5826751b | 148 | * |
p07gbar | 0:455d5826751b | 149 | * @param pwr Power status |
p07gbar | 0:455d5826751b | 150 | */ |
p07gbar | 0:455d5826751b | 151 | void power(bool pwr); |
p07gbar | 0:455d5826751b | 152 | |
p07gbar | 0:455d5826751b | 153 | /** Switch the peripheral between master and slave |
p07gbar | 0:455d5826751b | 154 | * |
p07gbar | 0:455d5826751b | 155 | * @param mastermode The peripherals master/slave status (I2S_MASTER/I2S_SLAVE) |
p07gbar | 0:455d5826751b | 156 | */ |
p07gbar | 0:455d5826751b | 157 | void masterslave(bool mastermode); |
p07gbar | 0:455d5826751b | 158 | |
p07gbar | 0:455d5826751b | 159 | /** Switch the peripheral between different wordsizes |
p07gbar | 0:455d5826751b | 160 | * |
p07gbar | 0:455d5826751b | 161 | * @param words The number of bits per word: 8,16,32 |
p07gbar | 0:455d5826751b | 162 | */ |
p07gbar | 0:455d5826751b | 163 | void wordsize(int words); |
p07gbar | 0:455d5826751b | 164 | |
p07gbar | 0:455d5826751b | 165 | /** Define the mclk frequency |
p07gbar | 0:455d5826751b | 166 | * |
p07gbar | 0:455d5826751b | 167 | * @param freq The frequency desired for the mclk |
p07gbar | 0:455d5826751b | 168 | */ |
p07gbar | 0:455d5826751b | 169 | void mclk_freq(int freq); |
p07gbar | 0:455d5826751b | 170 | |
p07gbar | 0:455d5826751b | 171 | /** Define the sample rate |
p07gbar | 0:455d5826751b | 172 | * |
p07gbar | 0:455d5826751b | 173 | * @param freq The desired sample rate frequency |
p07gbar | 0:455d5826751b | 174 | */ |
p07gbar | 0:455d5826751b | 175 | void frequency(int freq); |
p07gbar | 0:455d5826751b | 176 | |
p07gbar | 0:455d5826751b | 177 | /** Set the level that the fifo interrupts at |
p07gbar | 0:455d5826751b | 178 | * |
p07gbar | 0:455d5826751b | 179 | * @param level A number between 0 and 7 at which the fifo interrupts |
p07gbar | 0:455d5826751b | 180 | */ |
p07gbar | 0:455d5826751b | 181 | void set_interrupt_fifo_level(int level); |
p07gbar | 0:455d5826751b | 182 | |
p07gbar | 0:455d5826751b | 183 | /** Get the current FIFO level |
p07gbar | 0:455d5826751b | 184 | * |
p07gbar | 0:455d5826751b | 185 | * @return A number between 0 and 7 the FIFO is currently at |
p07gbar | 0:455d5826751b | 186 | */ |
p07gbar | 0:455d5826751b | 187 | int fifo_level(); |
p07gbar | 0:455d5826751b | 188 | |
p07gbar | 0:455d5826751b | 189 | /** Get the current number of samples in the FIFO |
p07gbar | 0:455d5826751b | 190 | * |
p07gbar | 0:455d5826751b | 191 | * @return A number showing how many samples are in the FIFO |
p07gbar | 0:455d5826751b | 192 | */ |
p07gbar | 0:455d5826751b | 193 | int fifo_points(); |
p07gbar | 0:455d5826751b | 194 | |
p07gbar | 0:455d5826751b | 195 | /** Set whether the peripheral is in stereo or mono mode: in mono the perifpheral sends out the same data twice |
p07gbar | 0:455d5826751b | 196 | * |
p07gbar | 0:455d5826751b | 197 | * @param stereomode Whether the peripheral is in stereo or mono: I2S_STEREO/I2S_MONO |
p07gbar | 0:455d5826751b | 198 | */ |
p07gbar | 0:455d5826751b | 199 | void stereomono(bool stereomode); |
p07gbar | 0:455d5826751b | 200 | |
p07gbar | 0:455d5826751b | 201 | /** Mute the peripheral |
p07gbar | 0:455d5826751b | 202 | * |
p07gbar | 0:455d5826751b | 203 | */ |
p07gbar | 0:455d5826751b | 204 | void mute(); |
p07gbar | 0:455d5826751b | 205 | |
p07gbar | 0:455d5826751b | 206 | /** Set the mute status of the peripheral |
p07gbar | 0:455d5826751b | 207 | * |
p07gbar | 0:455d5826751b | 208 | * @param mute_en Set whether the mute is enabled |
p07gbar | 0:455d5826751b | 209 | */ |
p07gbar | 0:455d5826751b | 210 | void mute(bool mute_en); |
p07gbar | 0:455d5826751b | 211 | |
p07gbar | 0:455d5826751b | 212 | /** Stop the peripheral |
p07gbar | 0:455d5826751b | 213 | * |
p07gbar | 0:455d5826751b | 214 | */ |
p07gbar | 0:455d5826751b | 215 | void stop(); |
p07gbar | 0:455d5826751b | 216 | |
p07gbar | 0:455d5826751b | 217 | /** Start the peripheral |
p07gbar | 0:455d5826751b | 218 | * |
p07gbar | 0:455d5826751b | 219 | */ |
p07gbar | 0:455d5826751b | 220 | void start(); |
p07gbar | 0:455d5826751b | 221 | |
p07gbar | 0:455d5826751b | 222 | /** Check the Clock and Pin setup went according to plan |
p07gbar | 0:455d5826751b | 223 | * |
p07gbar | 0:455d5826751b | 224 | * @return Setup okay? |
p07gbar | 0:455d5826751b | 225 | */ |
p07gbar | 0:455d5826751b | 226 | bool setup_ok(); |
p07gbar | 0:455d5826751b | 227 | |
p07gbar | 0:455d5826751b | 228 | /** Attach a function to be called when the FIFO triggers |
p07gbar | 0:455d5826751b | 229 | * |
p07gbar | 0:455d5826751b | 230 | * @param fptr A pointer to the function to be called |
p07gbar | 0:455d5826751b | 231 | */ |
p07gbar | 0:455d5826751b | 232 | void attach(void (*fptr)(void)) |
p07gbar | 0:455d5826751b | 233 | { |
p07gbar | 0:455d5826751b | 234 | if (_rxtx == I2S_TRANSMIT) |
p07gbar | 0:455d5826751b | 235 | { |
p07gbar | 0:455d5826751b | 236 | I2STXISR.attach(fptr); |
p07gbar | 0:455d5826751b | 237 | txisr = true; |
p07gbar | 0:455d5826751b | 238 | } |
p07gbar | 0:455d5826751b | 239 | else |
p07gbar | 0:455d5826751b | 240 | { |
p07gbar | 0:455d5826751b | 241 | I2SRXISR.attach(fptr); |
p07gbar | 0:455d5826751b | 242 | rxisr = true; |
p07gbar | 0:455d5826751b | 243 | } |
p07gbar | 0:455d5826751b | 244 | } |
p07gbar | 0:455d5826751b | 245 | |
p07gbar | 0:455d5826751b | 246 | /** Attach a member function to be called when the FIFO triggers |
p07gbar | 0:455d5826751b | 247 | * |
p07gbar | 0:455d5826751b | 248 | * @param tptr A pointer to the instance of the class |
p07gbar | 0:455d5826751b | 249 | * @param mptr A pointer to the member function |
p07gbar | 0:455d5826751b | 250 | */ |
p07gbar | 0:455d5826751b | 251 | template<typename T> |
p07gbar | 0:455d5826751b | 252 | void attach(T *tptr, void (T::*mptr)(void)) |
p07gbar | 0:455d5826751b | 253 | { |
p07gbar | 0:455d5826751b | 254 | if (_rxtx == I2S_TRANSMIT) |
p07gbar | 0:455d5826751b | 255 | { |
p07gbar | 0:455d5826751b | 256 | I2STXISR.attach(tptr, mptr); |
p07gbar | 0:455d5826751b | 257 | txisr = true; |
p07gbar | 0:455d5826751b | 258 | } |
p07gbar | 0:455d5826751b | 259 | else |
p07gbar | 0:455d5826751b | 260 | { |
p07gbar | 0:455d5826751b | 261 | I2SRXISR.attach(tptr, mptr); |
p07gbar | 0:455d5826751b | 262 | rxisr = true; |
p07gbar | 0:455d5826751b | 263 | } |
p07gbar | 0:455d5826751b | 264 | } |
p07gbar | 0:455d5826751b | 265 | |
p07gbar | 0:455d5826751b | 266 | private: |
p07gbar | 0:455d5826751b | 267 | |
p07gbar | 0:455d5826751b | 268 | void mclk_enable(bool mclk_en); |
p07gbar | 0:455d5826751b | 269 | |
p07gbar | 0:455d5826751b | 270 | void write_registers(); |
p07gbar | 0:455d5826751b | 271 | |
p07gbar | 0:455d5826751b | 272 | void pin_setup(); |
p07gbar | 0:455d5826751b | 273 | |
p07gbar | 0:455d5826751b | 274 | void fraction_estimator(float in, int * num, int * den); |
p07gbar | 0:455d5826751b | 275 | |
p07gbar | 0:455d5826751b | 276 | float mod(float in); |
p07gbar | 0:455d5826751b | 277 | |
p07gbar | 0:455d5826751b | 278 | void defaulter(); |
p07gbar | 0:455d5826751b | 279 | |
p07gbar | 0:455d5826751b | 280 | PinName _sd, _ws, _clk, _mclk; |
p07gbar | 0:455d5826751b | 281 | bool ws_d, clk_d, mclk_d; |
p07gbar | 0:455d5826751b | 282 | bool _rxtx; |
p07gbar | 0:455d5826751b | 283 | bool pwr; |
p07gbar | 0:455d5826751b | 284 | bool master; |
p07gbar | 0:455d5826751b | 285 | int wordwidth; |
p07gbar | 0:455d5826751b | 286 | char wordwidth_code; |
p07gbar | 0:455d5826751b | 287 | bool mclk_en; |
p07gbar | 0:455d5826751b | 288 | int mclk_frequency; |
p07gbar | 0:455d5826751b | 289 | int freq; |
p07gbar | 0:455d5826751b | 290 | bool stereo; |
p07gbar | 0:455d5826751b | 291 | bool muted; |
p07gbar | 0:455d5826751b | 292 | bool stopped; |
p07gbar | 0:455d5826751b | 293 | int interrupt_fifo_level; |
p07gbar | 0:455d5826751b | 294 | int pin_setup_err; |
p07gbar | 0:455d5826751b | 295 | int reg_write_err; |
p07gbar | 0:455d5826751b | 296 | bool deallocating; |
p07gbar | 0:455d5826751b | 297 | int old_freq; |
p07gbar | 0:455d5826751b | 298 | |
p07gbar | 0:455d5826751b | 299 | bool fourwire; |
p07gbar | 0:455d5826751b | 300 | |
p07gbar | 0:455d5826751b | 301 | int old_pre_num; |
p07gbar | 0:455d5826751b | 302 | int old_pre_den; |
p07gbar | 0:455d5826751b | 303 | int old_bitrate_div; |
p07gbar | 0:455d5826751b | 304 | static void _i2sisr(void); |
p07gbar | 0:455d5826751b | 305 | |
p07gbar | 0:455d5826751b | 306 | static FunctionPointer I2STXISR; |
p07gbar | 0:455d5826751b | 307 | static FunctionPointer I2SRXISR; |
p07gbar | 0:455d5826751b | 308 | |
p07gbar | 0:455d5826751b | 309 | static bool txisr; |
p07gbar | 0:455d5826751b | 310 | static bool rxisr; |
p07gbar | 0:455d5826751b | 311 | |
p07gbar | 0:455d5826751b | 312 | void write(int bufr[], int bufl[], int len); |
p07gbar | 0:455d5826751b | 313 | void read(int bufr[], int bufl[], int len); |
p07gbar | 0:455d5826751b | 314 | }; |
p07gbar | 0:455d5826751b | 315 | |
p07gbar | 0:455d5826751b | 316 | #endif |