vs10xx.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. /*
  2. * Copyright (C) 2003 by Pavel Chromy. All rights reserved.
  3. * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
  4. * Copyright (C) 2003-2004 by Streamit. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
  23. * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. * -
  34. *
  35. * This software has been inspired by all the valuable work done by
  36. * Jesper Hansen <jesperh@telia.com>. Many thanks for all his help.
  37. */
  38. /*
  39. * [COPYRIGHT] Copyright (C) STREAMIT BV
  40. *
  41. *
  42. */
  43. #define LOG_MODULE LOG_VS10XX_MODULE
  44. #include <stdlib.h>
  45. #include <sys/atom.h>
  46. #include <sys/event.h>
  47. #include <sys/timer.h>
  48. #include <sys/heap.h>
  49. #include <dev/irqreg.h>
  50. #include <sys/bankmem.h>
  51. #if (NUTOS_VERSION >= 433)
  52. #include <cpu_load.h>
  53. #endif
  54. #include "system.h"
  55. #include "vs10xx.h"
  56. #include "platform.h"
  57. #include "log.h"
  58. #include "portio.h" // for debug purposes only
  59. #include "spidrv.h" // for debug purposes only
  60. #include "watchdog.h"
  61. /*-------------------------------------------------------------------------*/
  62. /* global variable definitions */
  63. /*-------------------------------------------------------------------------*/
  64. /*-------------------------------------------------------------------------*/
  65. /* local variable definitions */
  66. /*-------------------------------------------------------------------------*/
  67. #define LOW 0
  68. #define HIGH 1
  69. #define MONO 0
  70. #define STEREO 1
  71. #define VsDeselectVs() SPIdeselect()
  72. #define VsSelectVs() SPIselect(SPI_DEV_VS10XX)
  73. /*-------------------------------------------------------------------------*/
  74. /* local variable definitions */
  75. /*-------------------------------------------------------------------------*/
  76. static volatile u_char vs_status = VS_STATUS_STOPPED;
  77. static u_short g_vs_type;
  78. static u_char VsPlayMode;
  79. static void VsLoadProgramCode(void);
  80. /*-------------------------------------------------------------------------*/
  81. /* local routines (prototyping) */
  82. /*-------------------------------------------------------------------------*/
  83. #define CODE_SIZE 437
  84. static prog_char atab[CODE_SIZE] = { /* Register addresses */
  85. 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  86. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  87. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  88. 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6,
  89. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  90. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  91. 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  92. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  93. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  94. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  95. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  96. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  97. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  98. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  99. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  100. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6,
  101. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  102. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  103. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  104. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  105. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  106. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  107. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  108. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  109. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  110. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  111. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  112. 6, 6, 6, 6, 6
  113. };
  114. prog_int dtab[CODE_SIZE] = { /* Data to write */
  115. 0x8030, 0x0030, 0x0717, 0xb080, 0x3c17, 0x0006, 0x5017, 0x3f00,
  116. 0x0024, 0x0006, 0x2016, 0x0012, 0x578f, 0x0000, 0x10ce, 0x2912,
  117. 0x9900, 0x0000, 0x004d, 0x4080, 0x184c, 0x0006, 0x96d7, 0x2800,
  118. 0x0d55, 0x0000, 0x0d48, 0x0006, 0x5b50, 0x3009, 0x0042, 0xb080,
  119. 0x8001, 0x4214, 0xbc40, 0x2818, 0xc740, 0x3613, 0x3c42, 0x3e00,
  120. 0xb803, 0x0014, 0x1b03, 0x0015, 0x59c2, 0x6fd6, 0x0024, 0x3600,
  121. 0x9803, 0x2812, 0x57d5, 0x0000, 0x004d, 0x2800, 0x2b40, 0x36f3,
  122. 0x0024, 0x804c, 0x3e10, 0x3814, 0x3e10, 0x780a, 0x3e13, 0xb80d,
  123. 0x3e03, 0xf805, 0x0006, 0x5595, 0x3009, 0x1415, 0x001b, 0xffd4,
  124. 0x0003, 0xffce, 0x0001, 0x000a, 0x2400, 0x16ce, 0xb58a, 0x0024,
  125. 0xf292, 0x9400, 0x6152, 0x0024, 0xfe02, 0x0024, 0x48b2, 0x0024,
  126. 0x454a, 0xb601, 0x36f3, 0xd805, 0x36f3, 0x980d, 0x36f0, 0x580a,
  127. 0x2000, 0x0000, 0x36f0, 0x1814, 0x8061, 0x3613, 0x0024, 0x3e12,
  128. 0xb817, 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3625, 0x0024, 0x0000,
  129. 0x800a, 0x3e10, 0xb803, 0x4194, 0xb805, 0x3e11, 0x0024, 0x3e11,
  130. 0xb807, 0x3e14, 0x7812, 0x3e14, 0xf80d, 0x3e03, 0xf80e, 0x0006,
  131. 0x0051, 0x2800, 0x24d5, 0x0000, 0x0024, 0xb888, 0x0012, 0x6404,
  132. 0x0405, 0x0000, 0x0024, 0x2800, 0x2158, 0x4094, 0x0024, 0x2400,
  133. 0x2102, 0x0000, 0x0024, 0x6498, 0x0803, 0xfe56, 0x0024, 0x48b6,
  134. 0x0024, 0x4dd6, 0x0024, 0x3a10, 0xc024, 0x32f0, 0xc024, 0xfe56,
  135. 0x0024, 0x48b6, 0x0024, 0x4dd6, 0x0024, 0x4384, 0x4483, 0x6396,
  136. 0x888c, 0xf400, 0x40d5, 0x3d00, 0x8024, 0x0006, 0x0091, 0x003f,
  137. 0xfec3, 0x0006, 0x0053, 0x3101, 0x8024, 0xfe60, 0x0024, 0x48be,
  138. 0x0024, 0xa634, 0x0c03, 0x4324, 0x0024, 0x4284, 0x2c02, 0x0006,
  139. 0x0011, 0x2800, 0x24d8, 0x3100, 0x8024, 0x0006, 0x5011, 0x3900,
  140. 0x8024, 0x0006, 0x0011, 0x3100, 0x984c, 0x4284, 0x904c, 0xf400,
  141. 0x4088, 0x2800, 0x2845, 0x0000, 0x0024, 0x3cf0, 0x3840, 0x3009,
  142. 0x3841, 0x3009, 0x3810, 0x2000, 0x0000, 0x0000, 0x2788, 0x3009,
  143. 0x1bd0, 0x2800, 0x2880, 0x3009, 0x1b81, 0x34f3, 0x1bcc, 0x36f3,
  144. 0xd80e, 0x36f4, 0xd80d, 0x36f4, 0x5812, 0x36f1, 0x9807, 0x36f1,
  145. 0x1805, 0x36f0, 0x9803, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2,
  146. 0x1815, 0x2000, 0x0000, 0x36f2, 0x9817, 0x80ad, 0x3e12, 0xb817,
  147. 0x3e12, 0x3815, 0x3e05, 0xb814, 0x3615, 0x0024, 0x0000, 0x800a,
  148. 0x3e10, 0x7802, 0x3e10, 0xf804, 0x3e11, 0x7810, 0x3e14, 0x7812,
  149. 0x2913, 0xc980, 0x3e14, 0xc024, 0x2913, 0xc980, 0x4088, 0x184c,
  150. 0xf400, 0x4005, 0x0000, 0x18c0, 0x6400, 0x0024, 0x0000, 0x1bc0,
  151. 0x2800, 0x3095, 0x0030, 0x0310, 0x2800, 0x3f80, 0x3801, 0x4024,
  152. 0x6400, 0x0024, 0x0000, 0x1a40, 0x2800, 0x3755, 0x0006, 0x55d0,
  153. 0x0000, 0x7d03, 0xb884, 0x184c, 0x3009, 0x3805, 0x3009, 0x0000,
  154. 0xff8a, 0x0024, 0x291d, 0x7b00, 0x48b2, 0x0024, 0x0000, 0x1841,
  155. 0x0006, 0x5010, 0x408a, 0xb844, 0x2900, 0x1300, 0x4088, 0x0024,
  156. 0x3000, 0x1bcc, 0x6014, 0x0024, 0x0030, 0x0351, 0x2800, 0x36d5,
  157. 0x0000, 0x0024, 0x0006, 0x0011, 0x3100, 0x0024, 0x0030, 0x0351,
  158. 0x3800, 0x0024, 0x2800, 0x3f80, 0x3901, 0x4024, 0x6400, 0x0024,
  159. 0x0030, 0x03d0, 0x2800, 0x3f55, 0x0000, 0x7d03, 0x0006, 0x55d0,
  160. 0xb884, 0x184c, 0x3009, 0x3805, 0x3009, 0x0000, 0xff8a, 0x0024,
  161. 0x291d, 0x7b00, 0x48b2, 0x0024, 0x408a, 0x9bcc, 0x0000, 0x1841,
  162. 0x2800, 0x3b55, 0x0006, 0x5010, 0x689a, 0x0024, 0x3000, 0x0024,
  163. 0x6014, 0x0024, 0x0030, 0x0392, 0x2800, 0x3e85, 0x0006, 0x0091,
  164. 0x0006, 0x0011, 0x0000, 0x1852, 0x0006, 0x0053, 0xb880, 0x2400,
  165. 0x0006, 0x0091, 0x3804, 0x8024, 0x0030, 0x0392, 0x3b00, 0x0024,
  166. 0x3901, 0x4024, 0x2800, 0x3f80, 0x3a01, 0x4024, 0x3801, 0x4024,
  167. 0xb880, 0x1bd3, 0x36f4, 0x5812, 0x36f1, 0x5810, 0x36f0, 0xd804,
  168. 0x36f0, 0x5802, 0x3405, 0x9014, 0x36f3, 0x0024, 0x36f2, 0x1815,
  169. 0x2000, 0x0000, 0x36f2, 0x9817, 0x0030
  170. };
  171. /*!
  172. * \addtogroup VS1003B
  173. */
  174. /*@{*/
  175. /*-------------------------------------------------------------------------*/
  176. /* start of code */
  177. /*-------------------------------------------------------------------------*/
  178. /*!
  179. * \brief Write a specified number of bytes to the VS10XX data interface.
  180. *
  181. * Decoder interrupts must have been disabled before calling this function.
  182. */
  183. static void VsSdiWrite(CONST u_char * data, u_short len)
  184. {
  185. VsSelectVs();
  186. while (len--)
  187. {
  188. SPIputByte(*data);
  189. data++;
  190. }
  191. VsDeselectVs();
  192. return;
  193. }
  194. /*!
  195. * \brief Write a specified number of bytes from program space to the
  196. * VS10XX data interface.
  197. *
  198. * This function is similar to VsSdiWrite() except that the data is
  199. * located in program space.
  200. */
  201. static void VsSdiWrite_P(PGM_P data, u_short len)
  202. {
  203. VsSelectVs();
  204. while (len--)
  205. {
  206. SPIputByte(PRG_RDB(data));
  207. data++;
  208. }
  209. VsDeselectVs();
  210. return;
  211. }
  212. /*!
  213. * \brief Write to a decoder register.
  214. *
  215. * Decoder interrupts must have been disabled before calling this function.
  216. */
  217. void VsRegWrite(u_char reg, u_short data)
  218. {
  219. u_char spimode;
  220. spimode = SPIgetmode();
  221. SPImode(SPEED_SLOW);
  222. VsSelectVs();
  223. cbi(VS_XCS_PORT, VS_XCS_BIT);
  224. SPIputByte(VS_OPCODE_WRITE);
  225. SPIputByte(reg);
  226. SPIputByte((u_char) (data >> 8));
  227. SPIputByte((u_char) data);
  228. sbi(VS_XCS_PORT, VS_XCS_BIT);
  229. VsDeselectVs();
  230. SPImode(spimode);
  231. return;
  232. }
  233. /*!
  234. * \brief determine if the stream is valid. If true, returns value; if false returns 0
  235. *
  236. */
  237. u_short VsStreamValid(void)
  238. {
  239. u_short value;
  240. u_short result;
  241. value = VsRegInfo(VS_HDAT1_REG);
  242. if (value > 0xFFE0)
  243. {
  244. value = 0xFFE0;
  245. }
  246. switch (value)
  247. {
  248. case 0x7665: /* WAV */
  249. case 0x4154: /* AAC DTS */
  250. case 0x4144: /* AAC ADIF */
  251. case 0x4D34: /* AAC .mp4 / .m4a */
  252. case 0x574D: /* WMA without broadcast patch*/
  253. {
  254. result= (g_vs_type==VS_VS1003? 0 : value);
  255. }
  256. break;
  257. case 0x576d: /* WMA with broadcast patch*/
  258. case 0x4D54: /* MIDI */
  259. case 0xFFE0: /* MP3 */
  260. {
  261. result=value;
  262. }
  263. break;
  264. default:
  265. {
  266. result=0;
  267. }
  268. }
  269. return(result);
  270. }
  271. /*
  272. * \brief Read from a register.
  273. *
  274. * Decoder interrupts must have been disabled before calling this function.
  275. *
  276. * \return Register contents.
  277. */
  278. static u_short VsRegRead(u_char reg)
  279. {
  280. u_short data;
  281. u_char spimode;
  282. spimode = SPIgetmode();
  283. SPImode(SPEED_SLOW);
  284. VsSelectVs();
  285. cbi(VS_XCS_PORT, VS_XCS_BIT);
  286. SPIputByte(VS_OPCODE_READ);
  287. SPIputByte(reg);
  288. data=SPIgetByte()<<8; // get MSB
  289. data |= SPIgetByte(); // get LSB
  290. sbi(VS_XCS_PORT, VS_XCS_BIT);
  291. VsDeselectVs();
  292. SPImode(spimode);
  293. return(data);
  294. }
  295. /*!
  296. * \brief read data from a specified register from the VS10XX
  297. *
  298. */
  299. u_short VsRegInfo(u_char reg)
  300. {
  301. u_char ief;
  302. u_short value;
  303. ief = VsPlayerInterrupts(0);
  304. value = VsRegRead(reg);
  305. VsPlayerInterrupts(ief);
  306. return(value);
  307. }
  308. /*!
  309. * \brief Enable or disable player interrupts.
  310. *
  311. * This routine is typically used by applications when dealing with
  312. * unprotected buffers.
  313. *
  314. * \param enable Disables interrupts when zero. Otherwise interrupts
  315. * are enabled.
  316. *
  317. * \return Zero if interrupts were disabled before this call.
  318. */
  319. u_char VsPlayerInterrupts(u_char enable)
  320. {
  321. u_char rc;
  322. NutEnterCritical();
  323. rc = (inb(EIMSK) & _BV(VS_DREQ_BIT)) != 0;
  324. if (enable)
  325. {
  326. sbi(EIMSK, VS_DREQ_BIT);
  327. }
  328. else
  329. {
  330. cbi(EIMSK, VS_DREQ_BIT);
  331. }
  332. NutExitCritical();
  333. return(rc);
  334. }
  335. /*
  336. * \brief Feed the decoder with data.
  337. *
  338. * This function serves two purposes:
  339. * - It is called by VsPlayerKick() to initially fill the decoder buffer.
  340. * - It is used as an interrupt handler for the decoder.
  341. *
  342. * Note that although this routine is an ISR, it is called from 'VsPlayerKick' as well
  343. */
  344. static void VsPlayerFeed(void *arg)
  345. {
  346. u_short j = 32;
  347. u_char ief;
  348. char *bp;
  349. size_t consumed;
  350. size_t available;
  351. // leave if not running.
  352. if ((vs_status != VS_STATUS_RUNNING) || (bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT)))
  353. {
  354. return;
  355. }
  356. /*
  357. * We are hanging around here some time and may block other important
  358. * interrupts. Disable decoder interrupts and enable global interrupts.
  359. */
  360. ief = VsPlayerInterrupts(0);
  361. sei();
  362. bp = 0;
  363. consumed = 0;
  364. available = 0;
  365. /*
  366. * Feed the decoder with j bytes or we ran out of data.
  367. */
  368. VsSelectVs();
  369. do
  370. {
  371. if (consumed >= available)
  372. {
  373. // Commit previously consumed bytes.
  374. if (consumed)
  375. {
  376. NutSegBufReadCommit(consumed);
  377. consumed = 0;
  378. }
  379. // All bytes consumed, request new.
  380. bp = NutSegBufReadRequest(&available);
  381. if (available == 0)
  382. {
  383. /* End of stream. */
  384. vs_status = VS_STATUS_EOF;
  385. break;
  386. }
  387. }
  388. if (available != 0) // We have some data in the buffer, feed it.
  389. {
  390. SPIputByte(*bp);
  391. bp++;
  392. consumed++;
  393. }
  394. /*
  395. * appearantly DREQ goes low when less then 32 byte are available
  396. * in the internal buffer (2048 bytes)
  397. */
  398. /* Allow 32 bytes to be sent as long as DREQ is set. This includes the one in progress */
  399. if (bit_is_set(VS_DREQ_PIN, VS_DREQ_BIT))
  400. {
  401. j = 32;
  402. }
  403. } while (--j); // bug solved: j-- counts one too many....
  404. VsDeselectVs();
  405. /* Finally re-enable the producer buffer. */
  406. NutSegBufReadLast(consumed);
  407. VsPlayerInterrupts(ief);
  408. }
  409. /*!
  410. * \brief Start playback.
  411. *
  412. * This routine will send the first MP3 data bytes to the
  413. * decoder. The data buffer
  414. * should have been filled before calling this routine.
  415. *
  416. * Decoder interrupts will be enabled.
  417. *
  418. * \return 0 on success, -1 otherwise.
  419. */
  420. int VsPlayerKick(void)
  421. {
  422. /*
  423. * Start feeding the decoder with data.
  424. */
  425. if (vs_status != VS_STATUS_RUNNING)
  426. {
  427. VsPlayerInterrupts(0);
  428. /*
  429. * for the VS1003 we need an extra reset
  430. * here before we start playing a stream...
  431. */
  432. // VsPlayerSetMode(VS_SM_RESET);
  433. // NutDelay(10);
  434. // LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));
  435. // LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));
  436. // LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));
  437. // LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));
  438. // LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));
  439. // VsLoadProgramCode();
  440. vs_status = VS_STATUS_RUNNING;
  441. VsPlayerFeed(NULL);
  442. VsPlayerInterrupts(1);
  443. }
  444. return(0);
  445. }
  446. /*!
  447. * \brief Stops the playback.
  448. *
  449. * This routine will stops the MP3 playback, VsPlayerKick() may be used
  450. * to resume the playback.
  451. *
  452. * \return 0 on success, -1 otherwise.
  453. */
  454. int VsPlayerStop(void)
  455. {
  456. u_char ief;
  457. ief = VsPlayerInterrupts(0);
  458. /* Check whether we need to stop at all to not overwrite other than running status */
  459. if (vs_status == VS_STATUS_RUNNING)
  460. vs_status = VS_STATUS_STOPPED;
  461. VsPlayerInterrupts(ief);
  462. return(0);
  463. }
  464. /*!
  465. * \brief Initialize the VS10xx hardware interface.
  466. *
  467. * \return 0 on success, -1 otherwise.
  468. */
  469. int VsPlayerInit(void)
  470. {
  471. /* Disable decoder interrupts. */
  472. VsPlayerInterrupts(0);
  473. /* Keep decoder in reset state. */
  474. cbi(VS_RESET_PORT, VS_RESET_BIT);
  475. /* Set VS10XX chip select output inactive for SCI bus (high) */
  476. sbi(VS_XCS_PORT, VS_XCS_BIT);
  477. /* Set SCK output low. */
  478. cbi(VS_SCK_PORT, VS_SCK_BIT);
  479. sbi(VS_SCK_DDR, VS_SCK_BIT);
  480. /*
  481. * Init SPI mode to no interrupts, enabled, MSB first, master mode,
  482. * rising clock and fosc/8 clock speed. Send an initial byte to
  483. * make sure SPIF is set. Note, that the decoder reset line is still
  484. * active.
  485. */
  486. NutDelay(4);
  487. SPImode(SPEED_SLOW);
  488. vs_status = VS_STATUS_STOPPED;
  489. /* Release decoder reset line. */
  490. sbi(VS_RESET_PORT, VS_RESET_BIT);
  491. /* Wait until DREQ is active
  492. * Write 0x9800 to SCI_CLOCKF
  493. * do another register write
  494. * wait at least 11000 clockcycles
  495. */
  496. NutDelay(4);
  497. /* Read the status register to determine the VS type. */
  498. g_vs_type = (VsRegRead(VS_STATUS_REG) >> 4) & 7;
  499. /* Force frequency change (see datasheet). */
  500. switch (g_vs_type)
  501. {
  502. case VS_VS1003:
  503. {
  504. VsRegWrite(VS_CLOCKF_REG, 0xE000); // 4.5x
  505. break;
  506. }
  507. default:
  508. {
  509. VsRegWrite(VS_CLOCKF_REG, 0x9800); // 2x
  510. break;
  511. }
  512. }
  513. NutDelay(50);
  514. // Datasheet requires 2 write instructions before speeding up SPI interface
  515. VsPlayerSetMode(0);
  516. VsSetVolume(0,0);
  517. NutDelay(50);
  518. // now switch to new speed...
  519. switch (g_vs_type)
  520. {
  521. case VS_VS1003:
  522. case VS_VS1053:
  523. {
  524. SPImode(SPEED_ULTRA_FAST);
  525. break;
  526. }
  527. case VS_VS1011e:
  528. default:
  529. {
  530. SPImode(SPEED_FAST);
  531. break;
  532. }
  533. }
  534. /* Register the interrupt routine */
  535. NutRegisterIrqHandler(&sig_INTERRUPT6, VsPlayerFeed, NULL);
  536. /* Rising edge will generate interrupts. */
  537. NutIrqSetMode(&sig_INTERRUPT6, NUT_IRQMODE_RISINGEDGE);
  538. /* Clear any spurious interrupt. */
  539. outp(BV(VS_DREQ_BIT), EIFR);
  540. return(0);
  541. }
  542. /*!
  543. * \brief Software reset the decoder.
  544. *
  545. * This function is typically called after VsPlayerInit() and at the end
  546. * of each track.
  547. *
  548. * \param mode Any of the following flags may be or'ed
  549. * - VS_SM_DIFF Left channel inverted.
  550. * - VS_SM_FFWD Fast forward.
  551. * - VS_SM_RESET Force hardware reset.
  552. * - VS_SM_PDOWN Switch to power down mode.
  553. * - VS_SM_BASS Bass/treble enhancer.
  554. *
  555. * \return 0 on success, -1 otherwise.
  556. */
  557. int VsPlayerReset(u_short mode)
  558. {
  559. /* Disable decoder interrupts and feeding. */
  560. VsPlayerInterrupts(0);
  561. vs_status = VS_STATUS_STOPPED;
  562. /* Software reset, set modes of decoder. */
  563. VsPlayerSetMode(VS_SM_RESET | mode);
  564. NutDelay(10);
  565. /* Clear any spurious interrupts. */
  566. outp(BV(VS_DREQ_BIT), EIFR);
  567. return(0);
  568. }
  569. /*!
  570. * \brief Set mode register of the decoder.
  571. *
  572. * \param mode Any of the following flags may be or'ed
  573. * - VS_SM_DIFF Left channel inverted.
  574. * - VS_SM_FFWD Fast forward.
  575. * - VS_SM_RESET Software reset.
  576. * - VS_SM_PDOWN Switch to power down mode.
  577. * - VS_SM_BASS Bass/treble enhancer.
  578. *
  579. * \return 0 on success, -1 otherwise.
  580. */
  581. int VsPlayerSetMode(u_short mode)
  582. {
  583. u_char ief;
  584. ief = VsPlayerInterrupts(0);
  585. /*
  586. * We need to be sure that the way of interfacing
  587. * is not corrupted by setting some new mode
  588. * We need to have SM_SDINEW & SM_SDISHARE set to '1'
  589. * at all times
  590. */
  591. mode |= (VS_SM_SDISHARE | VS_SM_SDINEW);
  592. VsRegWrite(VS_MODE_REG, mode);
  593. VsPlayerInterrupts(ief);
  594. return(0);
  595. }
  596. /*!
  597. * \brief Returns status of the player.
  598. *
  599. * \return Any of the following value:
  600. * - VS_STATUS_STOPPED Player is ready to be started by VsPlayerKick().
  601. * - VS_STATUS_RUNNING Player is running.
  602. * - VS_STATUS_EOF Player has reached the end of a stream after VsPlayerFlush() has been called.
  603. * - VS_STATUS_EMPTY Player runs out of data. VsPlayerKick() will restart it.
  604. */
  605. u_char VsGetStatus(void)
  606. {
  607. return(vs_status);
  608. }
  609. /*!
  610. * \brief Initialize decoder memory test and return result.
  611. *
  612. * \return Memory test result.
  613. * - Bit(s) Mask Meaning
  614. VS1011e/ VS1053
  615. VS1003
  616. * - 15 0x8000 0x8000 Test finished
  617. * - 14:7 Unused
  618. * - 14:10 Unused
  619. * - 9: 0x0200 Mux test succeeded
  620. * - 8: 0x0100 Good MAC RAM
  621. * - 7: 0x0080 Good I RAM
  622. * - 6: 0x0040 Mux test succeeded
  623. * - 6: 0x0040 Good Y RAM
  624. * - 5: 0x0020 Good I RAM
  625. * - 5: 0x0020 Good X RAM
  626. * - 4: 0x0010 Good Y RAM
  627. * - 4: 0x0010 Good I ROM 1
  628. * - 3: 0x0008 Good X RAM
  629. * - 3: 0x0008 Good I ROM 2
  630. * - 2: 0x0004 Good I ROM
  631. * - 2: 0x0004 Good Y ROM
  632. * - 1: 0x0002 Good Y ROM
  633. * - 1: 0x0002 Good X ROM 1
  634. * - 0: 0x0001 Good X ROM
  635. * - 0: 0x0001 Good X ROM 2
  636. * 0x807F 0x83FF All ok
  637. *
  638. * - return 0 on succes; rc otherwise
  639. */
  640. u_short VsMemoryTest(void)
  641. {
  642. u_short rc = -1;
  643. u_char ief;
  644. static prog_char mtcmd[] = { 0x4D, 0xEA, 0x6D, 0x54, 0x00, 0x00, 0x00, 0x00};
  645. VsPlayerReset(0);
  646. VsPlayerSetMode(VS_SM_TESTS);
  647. ief = VsPlayerInterrupts(0);
  648. VsSdiWrite_P(mtcmd, sizeof(mtcmd));
  649. NutDelay(40);
  650. rc = VsRegRead(VS_HDAT0_REG);
  651. VsPlayerInterrupts(ief);
  652. if ((VsGetType()==VS_VS1003) && (rc == 0x807F))
  653. {
  654. rc=0;
  655. }
  656. return(rc);
  657. }
  658. /*!
  659. * \brief Set volume.
  660. *
  661. * \param left Left channel volume.
  662. * \param right Right channel volume.
  663. *
  664. * \return 0 on success, -1 otherwise.
  665. */
  666. int VsSetVolume(u_char left, u_char right)
  667. {
  668. u_char ief;
  669. if(left < 0){
  670. left = 0;
  671. }
  672. if(right < 0){
  673. right = 0;
  674. }
  675. printf("%d %d", left, right);
  676. ief = VsPlayerInterrupts(0);
  677. VsRegWrite(VS_VOL_REG, (((u_short) left) << 8) | (u_short) right);
  678. VsPlayerInterrupts(ief);
  679. return(0);
  680. }
  681. /*!
  682. * \brief Get volume.
  683. *
  684. * \return u_short Volume.
  685. */
  686. u_short VsGetVolume()
  687. {
  688. u_char ief;
  689. u_short vol;
  690. ief = VsPlayerInterrupts(0);
  691. vol=VsRegRead(VS_VOL_REG);
  692. VsPlayerInterrupts(ief);
  693. return(vol);
  694. }
  695. /*!
  696. * \brief Return the number of the VS10xx chip.
  697. *
  698. * \return The actual type number as defined
  699. */
  700. u_short VsGetType(void)
  701. {
  702. return(g_vs_type);
  703. }
  704. /*!
  705. * \brief Return the number of the VS10xx chip.
  706. *
  707. * \return The actual type number coded in HEX!
  708. */
  709. u_short VsGetTypeHex(void)
  710. {
  711. switch (g_vs_type)
  712. {
  713. case VS_VS1003: return(0x03);
  714. default: break; /* Other codes use the actual number. */
  715. }
  716. return(g_vs_type);
  717. }
  718. /*!
  719. * \brief Sine wave beep.
  720. *
  721. * \param fsin Frequency.
  722. * \param ms Duration.
  723. *
  724. * \return 0 on success, -1 otherwise.
  725. */
  726. int VsBeep(u_char fsin, u_short ms)
  727. {
  728. u_char ief;
  729. static prog_char on[] = { 0x53, 0xEF, 0x6E};
  730. static prog_char off[] = { 0x45, 0x78, 0x69, 0x74};
  731. static prog_char end[] = { 0x00, 0x00, 0x00, 0x00};
  732. /* Disable decoder interrupts. */
  733. ief = VsPlayerInterrupts(0);
  734. VsPlayerSetMode(VS_SM_TESTS);
  735. fsin = (fsin* 16) + 56;
  736. VsSdiWrite_P(on, sizeof(on));
  737. VsSdiWrite(&fsin, 1);
  738. VsSdiWrite_P(end, sizeof(end));
  739. NutDelay(ms);
  740. VsSdiWrite_P(off, sizeof(off));
  741. VsSdiWrite_P(end, sizeof(end));
  742. /* Enable decoder interrupts. */
  743. VsPlayerInterrupts(ief);
  744. return(0);
  745. }
  746. /*!
  747. * \brief Sine wave beep start.
  748. *
  749. * \param fsin Frequency.
  750. *
  751. * \note this routine uses a fixed sample rate (12.000Hz) and
  752. * therefor the possible frequencies are limited.
  753. * Use 'VsBeepStartRaw' to generate a sinus with
  754. * an arbitrary freqeuncy
  755. *
  756. * \return 0 on success, -1 otherwise.
  757. */
  758. int VsBeepStart(u_char fsin)
  759. {
  760. return(VsBeepStartRaw(56 + (fsin & 7) * 9));
  761. }
  762. /*!
  763. * \brief Sine wave beep start in Raw mode.
  764. *
  765. * \param Raw: b7..b5 determines samplerate
  766. * while b4..b0 determines finepitch
  767. *
  768. * \note use the VS1003/VS1011 datasheet to figure out
  769. * which value to use for Fs (b7..b5) and
  770. * which value to use for S (b4..b0)
  771. *
  772. *
  773. * \return 0 on success, -1 otherwise.
  774. */
  775. int VsBeepStartRaw(u_char Raw)
  776. {
  777. u_char ief;
  778. static prog_char on[] = { 0x53, 0xEF, 0x6E};
  779. static prog_char end[] = { 0x00, 0x00, 0x00, 0x00};
  780. /* Disable decoder interrupts. */
  781. ief = VsPlayerInterrupts(0);
  782. VsPlayerSetMode(VS_SM_TESTS);
  783. VsSdiWrite_P(on, sizeof(on));
  784. VsSdiWrite(&Raw, 1);
  785. VsSdiWrite_P(end, sizeof(end));
  786. /* Enable decoder interrupts. */
  787. VsPlayerInterrupts(ief);
  788. return(0);
  789. }
  790. /*!
  791. * \brief Sine wave beep stop.
  792. *
  793. * \return 0 on success, -1 otherwise.
  794. */
  795. int VsBeepStop()
  796. {
  797. u_char ief;
  798. static prog_char off[] = { 0x45, 0x78, 0x69, 0x74};
  799. static prog_char end[] = { 0x00, 0x00, 0x00, 0x00};
  800. /* Disable decoder interrupts. */
  801. ief = VsPlayerInterrupts(0);
  802. VsSdiWrite_P(off, sizeof(off));
  803. VsSdiWrite_P(end, sizeof(end));
  804. /* Enable decoder interrupts. */
  805. VsPlayerInterrupts(ief);
  806. return(0);
  807. }
  808. static void VsLoadProgramCode(void)
  809. {
  810. int i;
  811. for (i=0;i<CODE_SIZE;i++)
  812. {
  813. VsRegWrite(PRG_RDB(&atab[i]), PRG_RDW(&dtab[i]));
  814. // kick watchdog on a regular base
  815. if(i%500==0)
  816. {
  817. WatchDogRestart();
  818. }
  819. }
  820. }
  821. /*@}*/