Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * This is free and unencumbered software released into the public domain.
  3. *
  4. * Anyone is free to copy, modify, publish, use, compile, sell, or
  5. * distribute this software, either in source code form or as a compiled
  6. * binary, for any purpose, commercial or non-commercial, and by any
  7. * means.
  8. *
  9. * In jurisdictions that recognize copyright laws, the author or authors
  10. * of this software dedicate any and all copyright interest in the
  11. * software to the public domain. We make this dedication for the benefit
  12. * of the public at large and to the detriment of our heirs and
  13. * successors. We intend this dedication to be an overt act of
  14. * relinquishment in perpetuity of all present and future rights to this
  15. * software under copyright law.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. * OTHER DEALINGS IN THE SOFTWARE.
  24. *
  25. * For more information, please refer to <http://unlicense.org>
  26. * -------------------------------------------------------------------------
  27. *
  28. * This is example code to 1) format an SPI Flash chip, and 2) copy raw
  29. * audio files (mono channel, 16 bit signed, 44100Hz) to it using the
  30. * SerialFlash library. The audio can then be played back using the
  31. * AudioPlaySerialflashRaw object in the Teensy Audio library.
  32. *
  33. * To convert a .wav file to the proper .RAW format, use sox:
  34. * sox input.wav -r 44100 -b 16 --norm -e signed-integer -t raw OUTPUT.RAW remix 1,2
  35. *
  36. * Note that the OUTPUT.RAW filename must be all caps and contain only the following
  37. * characters: A-Z, 0-9, comma, period, colon, dash, underscore. (The SerialFlash
  38. * library converts filenames to caps, so to avoid confusion we just enforce it here).
  39. *
  40. * It is a little difficult to see what is happening; aswe are using the Serial port
  41. * to upload files, we can't just throw out debug information. Instead, we use the LED
  42. * (pin 13) to convey state.
  43. *
  44. * While the chip is being formatted, the LED (pin 13) will toggle at 1Hz rate. When
  45. * the formatting is done, it flashes quickly (10Hz) for one second, then stays on
  46. * solid. When nothing has been received for 3 seconds, the upload is assumed to be
  47. * completed, and the light goes off.
  48. *
  49. * Use the 'rawfile-uploader.py' python script (included in the extras folder) to upload
  50. * the files. You can start the script as soon as the Teensy is turned on, and the
  51. * USB serial upload will just buffer and wait until the flash is formatted.
  52. *
  53. * This code was written by Wyatt Olson <wyatt@digitalcave.ca> (originally as part
  54. * of Drum Master http://drummaster.digitalcave.ca and later modified into a
  55. * standalone sample).
  56. *
  57. * Enjoy!
  58. */
  59. #include <SerialFlash.h>
  60. #include <SPI.h>
  61. //Buffer sizes
  62. #define USB_BUFFER_SIZE 128
  63. #define FLASH_BUFFER_SIZE 4096
  64. //Max filename length (8.3 plus a null char terminator)
  65. #define FILENAME_STRING_SIZE 13
  66. //State machine
  67. #define STATE_START 0
  68. #define STATE_SIZE 1
  69. #define STATE_CONTENT 2
  70. //Special bytes in the communication protocol
  71. #define BYTE_START 0x7e
  72. #define BYTE_ESCAPE 0x7d
  73. #define BYTE_SEPARATOR 0x7c
  74. //SPI Pins (these are the values on the Audio board; change them if you have different ones)
  75. #define MOSI 7
  76. #define MISO 12
  77. #define SCK 14
  78. #define CSPIN 6
  79. void setup(){
  80. Serial.begin(9600); //Teensy serial is always at full USB speed and buffered... the baud rate here is required but ignored
  81. pinMode(13, OUTPUT);
  82. //Set up SPI
  83. SPI.setMOSI(MOSI);
  84. SPI.setMISO(MISO);
  85. SPI.setSCK(SCK);
  86. SerialFlash.begin(CSPIN);
  87. //We start by formatting the flash...
  88. uint8_t id[5];
  89. SerialFlash.readID(id);
  90. SerialFlash.eraseAll();
  91. //Flash LED at 1Hz while formatting
  92. while (!SerialFlash.ready()) {
  93. delay(500);
  94. digitalWrite(13, HIGH);
  95. delay(500);
  96. digitalWrite(13, LOW);
  97. }
  98. //Quickly flash LED a few times when completed, then leave the light on solid
  99. for(uint8_t i = 0; i < 10; i++){
  100. delay(100);
  101. digitalWrite(13, HIGH);
  102. delay(100);
  103. digitalWrite(13, LOW);
  104. }
  105. digitalWrite(13, HIGH);
  106. //We are now going to wait for the upload program
  107. while(!Serial.available());
  108. SerialFlashFile flashFile;
  109. uint8_t state = STATE_START;
  110. uint8_t escape = 0;
  111. uint8_t fileSizeIndex = 0;
  112. uint32_t fileSize = 0;
  113. char filename[FILENAME_STRING_SIZE];
  114. char usbBuffer[USB_BUFFER_SIZE];
  115. uint8_t flashBuffer[FLASH_BUFFER_SIZE];
  116. uint16_t flashBufferIndex = 0;
  117. uint8_t filenameIndex = 0;
  118. uint32_t lastReceiveTime = millis();
  119. //We assume the serial receive part is finished when we have not received something for 3 seconds
  120. while(Serial.available() || lastReceiveTime + 3000 > millis()){
  121. uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);
  122. if (available){
  123. lastReceiveTime = millis();
  124. }
  125. for (uint16_t usbBufferIndex = 0; usbBufferIndex < available; usbBufferIndex++){
  126. uint8_t b = usbBuffer[usbBufferIndex];
  127. if (state == STATE_START){
  128. //Start byte. Repeat start is fine.
  129. if (b == BYTE_START){
  130. for (uint8_t i = 0; i < FILENAME_STRING_SIZE; i++){
  131. filename[i] = 0x00;
  132. }
  133. filenameIndex = 0;
  134. }
  135. //Valid characters are A-Z, 0-9, comma, period, colon, dash, underscore
  136. else if ((b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '.' || b == ',' || b == ':' || b == '-' || b == '_'){
  137. filename[filenameIndex++] = b;
  138. if (filenameIndex >= FILENAME_STRING_SIZE){
  139. //Error name too long
  140. flushError();
  141. return;
  142. }
  143. }
  144. //Filename end character
  145. else if (b == BYTE_SEPARATOR){
  146. if (filenameIndex == 0){
  147. //Error empty filename
  148. flushError();
  149. return;
  150. }
  151. //Change state
  152. state = STATE_SIZE;
  153. fileSizeIndex = 0;
  154. fileSize = 0;
  155. }
  156. //Invalid character
  157. else {
  158. //Error bad filename
  159. flushError();
  160. return;
  161. }
  162. }
  163. //We read 4 bytes as a uint32_t for file size
  164. else if (state == STATE_SIZE){
  165. if (fileSizeIndex < 4){
  166. fileSize = (fileSize << 8) + b;
  167. fileSizeIndex++;
  168. }
  169. else if (b == BYTE_SEPARATOR){
  170. state = STATE_CONTENT;
  171. flashBufferIndex = 0;
  172. escape = 0;
  173. if (SerialFlash.exists(filename)){
  174. SerialFlash.remove(filename); //It doesn't reclaim the space, but it does let you create a new file with the same name.
  175. }
  176. //Create a new file and open it for writing
  177. if (SerialFlash.create(filename, fileSize)) {
  178. flashFile = SerialFlash.open(filename);
  179. if (!flashFile) {
  180. //Error flash file open
  181. flushError();
  182. return;
  183. }
  184. }
  185. else {
  186. //Error flash create (no room left?)
  187. flushError();
  188. return;
  189. }
  190. }
  191. else {
  192. //Error invalid length requested
  193. flushError();
  194. return;
  195. }
  196. }
  197. else if (state == STATE_CONTENT){
  198. //Previous byte was escaped; unescape and add to buffer
  199. if (escape){
  200. escape = 0;
  201. flashBuffer[flashBufferIndex++] = b ^ 0x20;
  202. }
  203. //Escape the next byte
  204. else if (b == BYTE_ESCAPE){
  205. //Serial.println("esc");
  206. escape = 1;
  207. }
  208. //End of file
  209. else if (b == BYTE_START){
  210. //Serial.println("End of file");
  211. state = STATE_START;
  212. flashFile.write(flashBuffer, flashBufferIndex);
  213. flashFile.close();
  214. flashBufferIndex = 0;
  215. }
  216. //Normal byte; add to buffer
  217. else {
  218. flashBuffer[flashBufferIndex++] = b;
  219. }
  220. //The buffer is filled; write to SD card
  221. if (flashBufferIndex >= FLASH_BUFFER_SIZE){
  222. flashFile.write(flashBuffer, FLASH_BUFFER_SIZE);
  223. flashBufferIndex = 0;
  224. }
  225. }
  226. }
  227. }
  228. //Success! Turn the light off.
  229. digitalWrite(13, LOW);
  230. }
  231. void loop(){
  232. //Do nothing.
  233. }
  234. void flushError(){
  235. uint32_t lastReceiveTime = millis();
  236. char usbBuffer[USB_BUFFER_SIZE];
  237. //We assume the serial receive part is finished when we have not received something for 3 seconds
  238. while(Serial.available() || lastReceiveTime + 3000 > millis()){
  239. if (Serial.readBytes(usbBuffer, USB_BUFFER_SIZE)){
  240. lastReceiveTime = millis();
  241. }
  242. }
  243. }