[ FORK ] I2S library for FRDM 64F, forked from p07gbar/I2S

Fork of I2S by Giles Barton-Owen

Committer:
k4zuki
Date:
Tue Mar 29 09:07:43 2016 +0000
Revision:
10:94430ea76fc4
Parent:
8:b0e13a7e04eb
merge

Who changed what in which revision?

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