VS1053 & PIC24

Writing software for systems that use VLSI Solution's devices as slave codecs to a host microcontroller.
Post Reply
Posts: 8
Joined: Sat 2016-12-03 15:38

VS1053 & PIC24

Post by almen_80 » Thu 2016-12-08 11:41


I start a new thread asking for best practices confirming correct SPI transfer implementation.

I’m getting really troubles trying to use the Adafruit VS1053 Breakout using a PIC24. I’m able to read the right chip version but writing the registers (sanity check) doesn’t work as expected, following proposed implementation on player1053.c.

First of all I would like to confirm if I’m using the right SPI configuration:
Henrik wrote: 4) Check that your SPI clock polarity is correct: send data on the falling clock edge, VS10xx reads data on the rising edge by default.
Is the following assumption right?
CPOL = 0, CPHA=1 -> MODE 1

I'm running at the slowest clock speed and SPI speed should be 7.8125 kHz

The register "SCI_STATUS" returns after reset the right chip version (0x0048)

I think a good practice could be reading the registers. My questions are:
- Could I get more information about the current state of the chip from the registers?
- How to interpret the value “0x1F40” (and other values) of register read “SCI_AUDATA” ?
- What could be the reason writing both registers
    SCI_AICTRL2-> 0x7E57
but reading back:
    SCI_AICTRL2-> 0x7E57 ?
I really need some advice, I'm out if ideas what to check.

Thank you in advance!

User avatar
VLSI Staff
Posts: 2780
Joined: Tue 2010-06-22 13:43

Re: VS1053 & PIC24

Post by Panu » Thu 2016-12-08 12:49

VS10xx reads data on the rising edge by default.
Is the following assumption right?
CPOL = 0, CPHA=1 -> MODE 1
Hmm, no... I'd say it's CPOL=0, CPHA=0. https://en.wikipedia.org/wiki/Serial_Pe ... _and_phase

Make sure your data is stable at the rising edge.

More info: viewtopic.php?f=10&t=58

Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Posts: 8
Joined: Sat 2016-12-03 15:38

Re: VS1053 & PIC24

Post by almen_80 » Thu 2016-12-08 18:55

Hi Panu,

I'm able to read/write registers and play the hello. My problem was, obviously now for me, my implementation of the SPI byte exchange. :roll:

Here is the MP3-Hello code for PIC24s, maybe of interest for someone who is experimenting too with PIC and VS1053. As far as I understood it should be able to play other Hello formats (endFillByte was implemented).

Important for PIC24s is to disable the SPI befor speed changes and reactivate it after change.

Thank you for your help!

PS: my future step will be to implement my player as standalone under the VS1053.

Code: Select all

#define FCY 16000000UL

#include <stdio.h>
#include <stdlib.h>
#include <libpic30.h>
#include "mcc_generated_files/mcc.h"
#include "GenericTypeDefs.h"

UINT8 HelloMP3[] = {
    0xFF, 0xF2, 0x40, 0xC0, 0x19, 0xB7, 0x00, 0x14, 0x02, 0xE6, 0x5C, /* ..@.......\ */
    0x01, 0x92, 0x68, 0x01, 0xF1, 0x5E, 0x03, 0x08, 0xF0, 0x24, 0x80, /* ..h..^...$. */
    0x05, 0x9E, 0x20, 0xC6, 0xFC, 0x12, 0x32, 0x5C, 0xBF, 0xF9, 0xB9, /* .. ...2\... */
    0x20, 0x4A, 0x7F, 0x85, 0xEC, 0x4C, 0xCD, 0xC7, 0x27, 0xFE, 0x5C, /*  J...L..'.\ */
    0x34, 0x25, 0xCB, 0xE6, 0xFF, 0xFF, 0x8E, 0x42, 0xE1, 0xA0, 0x5E, /* 4%.....B..^ */
    0xCA, 0x6E, 0x30, 0x9F, 0xFF, 0xF8, 0xC2, 0x12, 0x84, 0xB9, 0x7C, /* .n0.......| */
    0xDC, 0x61, 0x09, 0x4A, 0x7F, 0xFF, 0xFF, 0xF9, 0x7D, 0x32, 0x51, /* .a.J....}2Q */
    0x09, 0x7C, 0xE1, 0xA5, 0x6E, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, /* .|..n...... */
    0x34, 0x41, 0x91, 0xF0, 0x11, 0x8F, 0x00, 0x0F, 0x81, 0x9C, 0x10, /* 4A......... */
    0xEE, 0x59, 0xCE, 0x56, 0x67, 0xFF, 0xF2, 0x42, 0xC0, 0xEC, 0x53, /* .Y.Vg..B..S */
    0x09, 0x15, 0xF9, 0xAA, 0xA8, 0x0D, 0xD9, 0x40, 0x00, 0xCA, 0x34, /* .......@..4 */
    0x53, 0xD9, 0x18, 0xAB, 0x7D, 0xF7, 0x89, 0x3F, 0x11, 0x38, 0x94, /* S...}..?.8. */
    0x82, 0x59, 0x93, 0x20, 0x6A, 0x0C, 0xEE, 0x8E, 0x58, 0xFA, 0x38, /* .Y. j...X.8 */
    0x82, 0xCA, 0xF0, 0x58, 0xBB, 0xDA, 0x0C, 0x50, 0x56, 0x1F, 0xBB, /* ...X...PV.. */
    0x18, 0x5D, 0x8B, 0x9F, 0xDA, 0x71, 0x4F, 0xFF, 0xBD, 0xFE, 0xEF, /* .]...qO.... */
    0x69, 0x36, 0x86, 0x3C, 0x50, 0xBB, 0x0A, 0x07, 0x89, 0x54, 0xF0, /* i6.<P....T. */
    0x88, 0x9F, 0x90, 0x95, 0x30, 0x94, 0x2E, 0x7E, 0xF0, 0x64, 0x96, /* ....0..~.d. */
    0x79, 0x08, 0x3E, 0x20, 0x97, 0x28, 0x34, 0x9C, 0x09, 0x7F, 0xD2, /* y.> .(4.... */
    0xC0, 0x01, 0x75, 0xF8, 0x05, 0x6B, 0x5F, 0x41, 0x17, 0x0B, 0xE7, /* ..u..k_A... */
    0xFF, 0xF2, 0x40, 0xC0, 0x61, 0xE5, 0x0B, 0x16, 0x09, 0xC6, 0xC5, /* ..@.a...... */
    0x74, 0x7B, 0xCC, 0x94, 0x7A, 0xF7, 0x80, 0x76, 0xB2, 0xD2, 0xF8, /* t{..z..v... */
    0x39, 0x06, 0x38, 0xFD, 0x71, 0xC5, 0xDE, 0x3A, 0x38, 0xBF, 0xD5, /* 9.8.q..:8.. */
    0xF7, 0x12, 0x37, 0xCB, 0xF5, 0x63, 0x0C, 0x9B, 0xCE, 0x77, 0x25, /* ..7..c...w% */
    0xED, 0xFB, 0x3D, 0x6B, 0x35, 0xF9, 0x6D, 0xD7, 0xF9, 0x2C, 0xD1, /* ..=k5.m..,. */
    0x97, 0x15, 0x87, 0x93, 0xA4, 0x49, 0x4A, 0x18, 0x16, 0x07, 0xA1, /* .....IJ.... */
    0x60, 0xF7, 0x52, 0x94, 0xDB, 0x02, 0x16, 0x70, 0xB2, 0xD8, 0x80, /* `.R....p... */
    0x30, 0xC2, 0x94, 0x40, 0x81, 0x74, 0x5A, 0x19, 0x7A, 0x80, 0x60, /* 0..@.tZ.z.` */
    0x41, 0x21, 0x46, 0x95, 0xD5, 0xC4, 0x40, 0xD2, 0x01, 0xC0, 0x01, /* A!F...@.... */
    0xDA, 0xD9, 0xA0, 0xB1, 0x01, 0xFF, 0xF2, 0x42, 0xC0, 0x82, 0x10, /* .......B... */
    0x0B, 0x12, 0xF9, 0x9E, 0xC9, 0x7E, 0x7A, 0xC6, 0x95, 0x55, 0x09, /* .....~z..U. */
    0x8B, 0x19, 0x5E, 0x8B, 0x26, 0xCA, 0xEB, 0x68, 0x8A, 0x05, 0x8F, /* ..^.&..h... */
    0x36, 0xA5, 0xA5, 0x03, 0xB8, 0x9C, 0xED, 0x24, 0x51, 0x59, 0x90, /* 6......$QY. */
    0xF6, 0xC5, 0x7D, 0xB5, 0xAD, 0xAF, 0xF6, 0x3B, 0x18, 0xEF, 0x3F, /* ..}....;..? */
    0xFF, 0xFF, 0x4E, 0xDE, 0x16, 0x66, 0x0B, 0xAA, 0x33, 0x23, 0xDD, /* ..N..f..3#. */
    0x9C, 0x4E, 0x6E, 0x55, 0x22, 0x9D, 0xA2, 0x40, 0xA6, 0x36, 0x31, /* .NnU"..@.61 */
    0x69, 0xA5, 0xE1, 0xD9, 0x7F, 0xF7, 0xC6, 0xCC, 0x48, 0x00, 0x0E, /* i.......H.. */
    0x90, 0x16, 0x00, 0x0F, 0xDE, 0x6E, 0x80, 0x11, 0x0C, 0x9A, 0x4F, /* .....n....O */
    0x56, 0xDB, 0x88, 0xD3, 0xB2, 0x1C, 0x00, 0xE0, 0x2E, 0x3E, 0xAC, /* V........>. */
    0xFF, 0xF2, 0x40, 0xC0, 0x1C, 0xE5, 0x19, 0x13, 0x31, 0x4E, 0xCD, /* ..@.....1N. */
    0x9E, 0xC3, 0x06, 0x71, 0x03, 0x85, 0xE5, 0xB5, 0x6D, 0x88, 0x50, /* ...q....m.P */
    0x8E, 0x0E, 0x17, 0x3B, 0x19, 0xFB, 0x4E, 0x3B, 0x99, 0xEF, 0x4C, /* ...;..N;..L */
    0x9E, 0xF7, 0x7B, 0x31, 0x7C, 0x3C, 0x5F, 0xFF, 0xF4, 0xF8, 0xE3, /* ..{1|<_.... */
    0x92, 0x42, 0x07, 0x8E, 0x83, 0x8E, 0x0F, 0x05, 0x08, 0x91, 0xA3, /* .B......... */
    0x16, 0xE2, 0xDF, 0xB7, 0x62, 0x60, 0x48, 0x31, 0x3C, 0xFF, 0xD4, /* ....b`H1<.. */
    0x9E, 0x0C, 0x68, 0x00, 0x77, 0x54, 0xE3, 0x1E, 0x05, 0xC5, 0xF8, /* ..h.wT..... */
    0xEA, 0x8D, 0x82, 0x9D, 0x08, 0xA9, 0x06, 0x8D, 0x1E, 0x5D, 0x7C, /* .........]| */
    0x7F, 0x08, 0xC0, 0x50, 0x45, 0x42, 0xD0, 0x36, 0xF8, 0xB2, 0x4D, /* ...PEB.6..M */
    0x53, 0x0C, 0x80, 0x3B, 0x4D, 0xFF, 0xF2, 0x42, 0xC0, 0x2F, 0x3C, /* S..;M..B./< */
    0x25, 0x19, 0x29, 0xFE, 0xBC, 0x2E, 0xC4, 0xD0, 0x99, 0x4C, 0x48, /* %.)......LH */
    0xB0, 0x9C, 0x49, 0xD2, 0x1A, 0x2D, 0x02, 0xC2, 0x79, 0x69, 0x16, /* ..I..-..yi. */
    0x92, 0xA8, 0xC5, 0xAB, 0x45, 0x5A, 0x68, 0xE8, 0x75, 0x57, 0xCD, /* ....EZh.uW. */
    0xF1, 0xB9, 0xAA, 0x13, 0x88, 0xE4, 0x87, 0x42, 0x15, 0xB3, 0x58, /* .......B..X */
    0xF5, 0xA3, 0x46, 0xB1, 0xCF, 0xD3, 0x59, 0x7E, 0xBA, 0xB5, 0xA7, /* ..F...Y~... */
    0x6B, 0x0B, 0x17, 0x57, 0x6B, 0x5C, 0x4A, 0xCD, 0x53, 0x76, 0x2A, /* k..Wk\J.Sv* */
    0x1D, 0x28, 0xC5, 0x1C, 0x76, 0x5C, 0xDD, 0x0A, 0x00, 0x4B, 0xC0, /* .(..v\...K. */
    0x1B, 0xCA, 0xA8, 0xE9, 0x81, 0x5B, 0xA6, 0xDC, 0xA4, 0x59, 0x13, /* .....[...Y. */
    0xFC, 0xBA, 0x8F, 0x98, 0x79, 0x44, 0x25, 0xC9, 0x35, 0x38, 0xCA, /* ....yD%.58. */
    0xFF, 0xF2, 0x40, 0xC0, 0xB9, 0x7D, 0x1A, 0x13, 0x79, 0x6A, 0xC8, /* ..@..}..yj. */
    0x3E, 0xC4, 0x46, 0x94, 0x8D, 0x3C, 0x67, 0x85, 0xB1, 0xA8, 0x89, /* >.F..<g.... */
    0xC0, 0xF2, 0xE6, 0x2F, 0x9D, 0x7C, 0xC9, 0xB4, 0xBE, 0xCF, 0xE1, /* .../.|..... */
    0x7D, 0xFE, 0x1F, 0x03, 0x00, 0x12, 0x84, 0x72, 0x8C, 0xE7, 0xD8, /* }......r... */
    0x5E, 0xC9, 0xA9, 0x01, 0xBA, 0x9B, 0xC4, 0x10, 0x5C, 0x70, 0x2E, /* ^.......\p. */
    0x6C, 0x48, 0xE7, 0x8C, 0x15, 0x0B, 0x06, 0x01, 0xE5, 0xFF, 0xFF, /* lH......... */
    0xD4, 0x0D, 0x00, 0x0F, 0xCE, 0x58, 0x95, 0x61, 0xA8, 0x9E, 0x7B, /* .....X.a..{ */
    0x19, 0x98, 0xB0, 0xF0, 0xC6, 0x72, 0x82, 0xD5, 0x27, 0x06, 0x47, /* .....r..'.G */
    0x41, 0x22, 0x0F, 0x65, 0x93, 0xC9, 0x8A, 0x09, 0x19, 0x48, 0x1B, /* A".e.....H. */
    0xBD, 0xD6, 0x64, 0x1A, 0xAC, 0xFF, 0xF2, 0x42, 0xC0, 0xF1, 0x11, /* ..d....B... */
    0x25, 0x14, 0x22, 0x06, 0xBC, 0x0E, 0xD4, 0x4E, 0x99, 0x90, 0xA8, /* %."....N... */
    0xD8, 0xB7, 0xAD, 0x5D, 0x3E, 0xAF, 0x6E, 0xBE, 0x66, 0x83, 0xA4, /* ...]>.n.f.. */
    0xE3, 0xC2, 0xE0, 0x29, 0x43, 0x87, 0x5F, 0x4F, 0x27, 0x9C, 0x2C, /* ...)C._O'., */
    0xD0, 0x91, 0xF3, 0x87, 0x9B, 0x54, 0xED, 0xD1, 0xB4, 0xF3, 0x39, /* .....T....9 */
    0x87, 0x22, 0x06, 0x86, 0x0D, 0x71, 0xE4, 0x6F, 0x2A, 0x08, 0x04, /* ."...q.o*.. */
    0xC0, 0x03, 0x2A, 0xB1, 0xE2, 0x05, 0x4D, 0x64, 0xA1, 0x9C, 0xA6, /* ..*...Md... */
    0x0D, 0x41, 0xA6, 0xF2, 0x7A, 0xC1, 0x30, 0xC3, 0x38, 0x26, 0x09, /* .A..z.0.8&. */
    0x50, 0x08, 0xC4, 0xF6, 0x30, 0x0C, 0xA6, 0xA9, 0x17, 0x00, 0x13, /* P...0...... */
    0x0C, 0xDC, 0xC4, 0x2F, 0x28, 0xEB, 0x3F, 0xCD, 0x7A, 0x3D, 0x2F, /* .../(.?.z=/ */
    0xFF, 0xF2, 0x40, 0xC0, 0x18, 0x6F, 0x2E, 0x13, 0xA1, 0xF2, 0xBC, /* ..@..o..... */
    0x36, 0xCB, 0x4E, 0x99, 0x6E, 0xFC, 0xEE, 0xC5, 0xF0, 0xA0, 0xB7, /* 6.N.n...... */
    0x92, 0xD4, 0xEE, 0x79, 0x7C, 0x50, 0x5D, 0xE5, 0x04, 0x94, 0xA9, /* ...y|P].... */
    0x76, 0xCF, 0x6C, 0x70, 0xDD, 0x0D, 0xD4, 0xEE, 0xED, 0x98, 0xE8, /* v.lp....... */
    0xC8, 0x35, 0x36, 0x7A, 0x0C, 0x05, 0x80, 0x03, 0xBC, 0xBE, 0x91, /* .56z....... */
    0x00, 0x7C, 0xAE, 0x65, 0xB8, 0x91, 0xA3, 0x33, 0xBA, 0x68, 0x60, /* .|.e...3.h` */
    0xD4, 0x1A, 0x66, 0xF8, 0x43, 0xA0, 0x20, 0x89, 0xE7, 0x80, 0xD8, /* ..f.C. .... */
    0x1E, 0x4F, 0xA0, 0x04, 0x60, 0x06, 0x0A, 0xA4, 0x91, 0x24, 0xFA, /* .O..`....$. */
    0x9F, 0x57, 0x53, 0xF4, 0x7A, 0xDB, 0x5F, 0x56, 0xE3, 0x6E, 0x0B, /* .WS.z._V.n. */
    0x8B, 0x3A, 0x1C, 0xF9, 0x5E, 0xFF, 0xF2, 0x42, 0xC0, 0xB1, 0x00, /* .:..^..B... */
    0x38, 0x14, 0x09, 0xEE, 0xB4, 0x36, 0xD3, 0x4E, 0x99, 0xA4, 0x78, /* 8....6.N..x */
    0x94, 0x73, 0xC4, 0x66, 0x30, 0xF5, 0xEA, 0xDB, 0xBA, 0x67, 0x67, /* .s.f0....gg */
    0x95, 0x6B, 0xAB, 0x68, 0x5D, 0x08, 0xA1, 0x39, 0x56, 0xAB, 0x1E, /* .k.h]..9V.. */
    0xD5, 0x03, 0xE8, 0x01, 0x70, 0x00, 0xB3, 0x93, 0x33, 0x19, 0x8C, /* ....p...3.. */
    0x61, 0x8F, 0xBB, 0x5D, 0x24, 0x12, 0x63, 0xD3, 0x4B, 0x5D, 0x91, /* a..]$.c.K]. */
    0x08, 0x43, 0x22, 0x56, 0x1A, 0xC5, 0x10, 0x21, 0x84, 0xA8, 0xEA, /* .C"V...!... */
    0x80, 0xBF, 0x16, 0x8E, 0x3D, 0x46, 0x18, 0x9C, 0x6E, 0x9A, 0x91, /* ....=F..n.. */
    0xE6, 0xC9, 0x6F, 0xD2, 0x7D, 0x27, 0xD7, 0xE9, 0x6B, 0xFF, 0x0A, /* ..o.}'..k.. */
    0x03, 0x43, 0x89, 0xD5, 0xBF, 0x52, 0x97, 0x0A, 0x25, 0x95, 0x0D, /* .C...R..%.. */
    0xFF, 0xF2, 0x40, 0xC0, 0xF5, 0xC3, 0x41, 0x13, 0x81, 0xEE, 0xA8, /* ..@...A.... */
    0x5E, 0xD3, 0x44, 0x98, 0xFC, 0xCF, 0x97, 0xF9, 0x58, 0xB5, 0x33, /* ^.D.....X.3 */
    0xB1, 0x85, 0x47, 0x86, 0xD7, 0x98, 0x01, 0x3B, 0xA3, 0x4F, 0x7E, /* ..G....;.O~ */
    0x04, 0xA6, 0xC3, 0x39, 0x21, 0x70, 0x27, 0x62, 0xB5, 0x18, 0x10, /* ...9!p'b... */
    0x09, 0x99, 0x00, 0x8B, 0x7E, 0xF2, 0xBF, 0x52, 0x18, 0x26, 0x30, /* ....~..R.&0 */
    0x1C, 0xB0, 0x01, 0x49, 0x30, 0xE0, 0xC3, 0x11, 0x46, 0x05, 0xCC, /* ...I0...F.. */
    0x49, 0x14, 0x28, 0xB2, 0xED, 0x4B, 0x57, 0x5A, 0x2F, 0xB7, 0x46, /* I.(..KWZ/.F */
    0x63, 0x34, 0xD2, 0xDA, 0x9F, 0x56, 0x32, 0xB7, 0xA2, 0x25, 0xFF, /* c4...V2..%. */
    0x94, 0x28, 0x33, 0x7F, 0x3B, 0xC4, 0x50, 0xEC, 0xB1, 0xE2, 0x26, /* .(3.;.P...& */
    0xA1, 0xB7, 0x07, 0x7F, 0xFB, 0xFF, 0xF2, 0x42, 0xC0, 0x67, 0x6A, /* .......B.gj */
    0x4C, 0x13, 0xF9, 0x6A, 0x90, 0x7E, 0xDB, 0x44, 0x94, 0x3F, 0xFF, /* L..j.~.D.?. */
    0x14, 0xD6, 0x2A, 0xFF, 0xFF, 0xC1, 0x34, 0x8C, 0x48, 0x22, 0x00, /* ..*...4.H". */
    0x06, 0x8F, 0x21, 0xFD, 0x64, 0x60, 0x04, 0x92, 0x42, 0xEA, 0x74, /* ..!.d`..B.t */
    0x32, 0x37, 0xAA, 0x5A, 0x9F, 0x67, 0x01, 0x8B, 0x3F, 0x37, 0x31, /* 27.Z.g..?71 */
    0xDD, 0x06, 0x3C, 0x01, 0x34, 0x30, 0xE0, 0x5C, 0x78, 0x78, 0xCB, /* ..<.40.\xx. */
    0xD6, 0xF1, 0x31, 0x8A, 0x69, 0x61, 0x93, 0x92, 0x42, 0xCE, 0x4B, /* ..1.ia..B.K */
    0xC5, 0x02, 0x4E, 0x73, 0xC6, 0x24, 0x30, 0xCD, 0x08, 0x66, 0xC6, /* ..Ns.$0..f. */
    0x35, 0xAB, 0xA2, 0x3D, 0x2F, 0xB3, 0xBD, 0x34, 0x87, 0x13, 0xEE, /* 5..=/..4... */
    0x71, 0x45, 0x68, 0xFA, 0xEA, 0x05, 0x84, 0x41, 0x36, 0x4C, 0x9A, /* qEh....A6L. */
    0xFF, 0xF2, 0x40, 0xC0, 0xC9, 0x92, 0x56, 0x13, 0xD0, 0x6E, 0x70, /* ..@...V..np */
    0x54, 0xD3, 0xCC, 0x28, 0x06, 0xD7, 0x0E, 0xA4, 0x1D, 0x9C, 0x9D, /* T..(....... */
    0xD9, 0xA9, 0x88, 0x7B, 0xB5, 0xA3, 0x56, 0xB7, 0x4B, 0x4B, 0x5A, /* ...{..V.KKZ */
    0x9B, 0x2C, 0xA9, 0xAD, 0x6F, 0x99, 0x6C, 0xC0, 0x4C, 0x14, 0x14, /* .,..o.l.L.. */
    0xEF, 0xB4, 0x20, 0x91, 0x5F, 0xBC, 0x81, 0x41, 0x41, 0x5D, 0xD4, /* .. ._..AA]. */
    0x20, 0xBD, 0x05, 0x1A, 0x6F, 0xE2, 0x68, 0x56, 0x41, 0x41, 0x57, /*  ...o.hVAAW */
    0xF9, 0xBF, 0x89, 0x82, 0x8E, 0xC7, 0x8F, 0x0A, 0x0A, 0x09, 0x37, /* ..........7 */
    0xF1, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x09, 0x05, 0x37, 0xFF, 0x10, /* ........7.. */
    0x50, 0x50, 0x53, 0x65, 0xFF, 0xFF, 0xFD, 0x75, 0xDF, 0xFF, 0xFF, /* PPSe...u... */
    0x68, 0x4F, 0xFF, 0x84, 0x70, 0xFF, 0xF2, 0x42, 0xC0, 0x27, 0x50, /* hO..p..B.'P */
    0x5F, 0x17, 0xE8, 0x82, 0x3C, 0x11, 0x58, 0x18, 0x01, 0x55, 0x48, /* _...<.X..UH */
    0xBC, 0x52, 0xFC, 0x4A, 0x4C, 0x3C, 0xD5, 0xF6, 0x11, 0x2D, 0xBF, /* .R.JL<...-. */
    0xEA, 0x03, 0x5C, 0x57, 0x29, 0xBF, 0xC3, 0x75, 0x1C, 0xE6, 0xDD, /* ..\W)..u... */
    0xBF, 0xED, 0xEF, 0xD0, 0x98, 0x77, 0x71, 0x95, 0x73, 0xFF, 0xED, /* .....wq.s.. */
    0x54, 0xBE, 0xD5, 0xEE, 0xAE, 0xC2, 0xD5, 0x0B, 0xFF, 0xF1, 0x97, /* T.......... */
    0x8A, 0xE4, 0x42, 0x09, 0x99, 0xB1, 0xEA, 0x94, 0xDC, 0x78, 0xB5, /* ..B......x. */
    0x34, 0x0F, 0xF1, 0x8F, 0xFC, 0x15, 0xF6, 0xFA, 0xB1, 0x47, 0xA9, /* 4........G. */
    0x6C, 0x67, 0x43, 0x8B, 0xF2, 0x76, 0x22, 0xED, 0xDA, 0x85, 0xBA, /* lgC..v".... */
    0x2F, 0xC7, 0xF9, 0xCF, 0xFC, 0xDB, 0x46, 0x2E, 0x50, 0x0A, 0x84, /* /.....F.P.. */
    0xFF, 0xF2, 0x40, 0xC0, 0xC6, 0x4A, 0x59, 0x28, 0x2B, 0x19, 0xE0, /* ..@..JY(+.. */
    0x01, 0x89, 0x78, 0x00, 0x52, 0x85, 0x3C, 0x8E, 0x54, 0x9A, 0x48, /* ..x.R.<.T.H */
    0x5A, 0x72, 0x32, 0x94, 0xBF, 0x43, 0x4F, 0x24, 0x53, 0x4B, 0xEC, /* Zr2..CO$SK. */
    0x4B, 0x99, 0x0E, 0x66, 0x1F, 0xFF, 0xCE, 0x7F, 0xFF, 0x3F, 0x10, /* K..f.....?. */
    0xAE, 0x82, 0x62, 0x71, 0x34, 0x18, 0x59, 0x9B, 0x51, 0xC7, 0x59, /* ..bq4.Y.Q.Y */
    0xCE, 0xEE, 0xA5, 0xFE, 0x02, 0xBB, 0x30, 0x91, 0x49, 0xD5, 0x4B, /* ......0.I.K */
    0xF3, 0xDC, 0x9A, 0xA9, 0x57, 0x8E, 0x72, 0x10, 0xC0, 0x5D, 0x60, /* ....W.r..]` */
    0x67, 0xFC, 0x7D, 0xD6, 0xBA, 0xDD, 0xB3, 0x8B, 0x5A, 0x0A, 0x4C, /* g.}.....Z.L */
    0x41, 0x4D, 0x45, 0x33, 0x2E, 0x39, 0x33, 0xAA, 0xAA, 0xAA, 0xAA, /* AME3.93.... */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x54, 0x41, 0x47, 0x48, 0x65, 0x6C, /* .....TAGHel */
    0x6C, 0x6F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* lo          */
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /*             */
    0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x6E, 0x75, 0x2D, 0x4B, /*      Panu-K */
    0x72, 0x69, 0x73, 0x74, 0x69, 0x61, 0x6E, 0x20, 0x50, 0x6F, 0x69, /* ristian Poi */
    0x6B, 0x73, 0x61, 0x6C, 0x6F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* ksalo       */
    0x20, 0x20, 0x56, 0x53, 0x44, 0x53, 0x50, 0x20, 0x54, 0x65, 0x73, /*   VSDSP Tes */
    0x74, 0x69, 0x6E, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /* ting        */
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /*             */
    0x20, 0x20, 0x20, 0x4D, 0x50, 0x33, 0x20, 0x48, 0x65, 0x6C, 0x6C, /*    MP3 Hell */
    0x6F, 0x2C, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x20, 0x20, /* o, World!   */
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, /*             */
    0x00, /* . */

// VS10XX Operations //
#define VS_WRITE_COMMAND 0x02 /** VS10xx SCI Write Command byte is 0x02 */
#define VS_READ_COMMAND 0x03 /** VS10xx SCI Read Command byte is 0x03 */

/* SCI registers */

#define SCI_MODE        0x00
#define SCI_STATUS      0x01
#define SCI_CLOCKF      0x03
#define SCI_AUDATA      0x05
#define SCI_WRAM        0x06
#define SCI_WRAMADDR    0x07
#define SCI_HDAT0       0x08 /* VS1063, VS1053, VS1033, VS1003, VS1011 */
#define SCI_HDAT1       0x09 /* VS1063, VS1053, VS1033, VS1003, VS1011 */
#define SCI_VOL         0x0B
#define SCI_AICTRL1     0x0D /* VS1063, VS1053, VS1033, VS1003, VS1011 */
#define SCI_AICTRL2     0x0E

#define SM_RESET          (1<< 2)
#define SM_CANCEL         (1<< 3) /* VS1063, VS1053 */
#define SM_TESTS          (1<< 5)
#define SM_SDINEW         (1<<11)

/* Following are for VS1053 and VS1063 */
#define SC_MULT_53_35X 0x8000

/* Following are for VS1053 and VS1063 */
#define SC_ADD_53_10X 0x0800

#define PAR_END_FILL_BYTE 0x1e06 /* VS1063, VS1053 */

/* The following macro is for VS1063, VS1053, VS1033, VS1003, VS1103.
   Divide hz by two when calling if SM_CLK_RANGE = 1 */
#define HZ_TO_SC_FREQ(hz) (((hz)-8000000+2000)/4000)

#define SDCARD_setHigh() { _LATB3 = 1;}

#define min(a,b) (((a)<(b))?(a):(b))

// SPI Speeds according data sheet
//  CLKI= 1 x XTALI = 12 MHz -> maximal SCI read speed= 1,7 MHz
#define SPI1BRGL_RESET 0x0007 // 1 MHz
// minimal CLKI= 3.5 x XTALI = 43 MHz -> maximal SCI read speed= 6 MHz
#define SPI1BRGL_SCI   0x0001 // 4 MHz
// no limit
#define SPI1BRGL_SDI   0x0000 // 8 MHz

 * Although the timing is derived from the internal clock CLKI, the system always 
 * starts up in 1:0× mode, thus CLKI=XTALI. After you have configured a higher 
 * clock through SCI_CLOCKF and waited for DREQ to rise, you can use a higher 
 * SPI speed as well.
#define setSpeedForReset() {SCI_SPEED = SPI1BRGL_RESET;}
#define setSpeedForSCI()   {SCI_SPEED = SPI1BRGL_SCI;  }


UINT8 SPI_Exchange8bit(UINT8 data) {
    while (SPI1STATLbits.SPITBF == true);
    SPI1BUFL = data;

    while (SPI1STATLbits.SPIRBE == true);
    return SPI1BUFL;

void SPI_SendEndFillByte(UINT16 endFillByte) {
    SPI_Exchange8bit(endFillByte >> 8);
    SPI_Exchange8bit(endFillByte & 0xFF);

 * Version: 1.22, 2014-12-19, page 22
 * 7.4.4 SCI Timing Diagram 
 * Note Because tWL + tWH + tH is 6×CLKI + 25 ns, the maximum speed for SCI reads is CLKI/7
void setSCISpeed() {
    SPI1CON1Lbits.SPIEN = 0;
    SPI1CON1Lbits.SPIEN = 1;

void setSDISpeed() {
    SPI1CON1Lbits.SPIEN = 0;
    SPI1CON1Lbits.SPIEN = 1;

 * 7.4.2 SCI Write
 * @param addressbyte
 * @param highByte
 * @param lowByte
void writeRegister(UINT8 addressbyte, UINT8 highByte, UINT8 lowByte) {
    while (!DREQ_GetValue()); //Wait after IC is available
    XCS_SetLow(); //Select CS

    // 1. instruction byte
    // 2. address byte
    // 3. write 16-bit data word.
     * Note: VS1053b sets DREQ low after each SCI operation. The duration depends 
     * on the operation. It is not allowed to finish a new SCI/SDI operation 
     * before DREQ is high again.
    while (!DREQ_GetValue());

    // After the word has been shifted in and the last clock has been sent, XCS 
    // should be pulled high to end the WRITE sequence.

 * @param addressbyte
 * @param data
void writeRegister16(UINT8 addressbyte, UINT16 data) {
    writeRegister(addressbyte, data >> 8, data & 0xFF);

 * @param addressbyte
 * @return 
UINT16 readRegister(UINT8 addressbyte) {
    while (!DREQ_GetValue()); //Wait for after IC is available
    XCS_SetLow(); // Select CS

    // 1. instruction byte
    // 2. address byte
    // 3. read 16-bit data word.
    SPI_Exchange8bit(VS_READ_COMMAND); //Read instruction

    UINT16 highByte = SPI_Exchange8bit(0xFF); //Read the first byte
    while (!DREQ_GetValue()); //Wait after command is complete
    UINT16 lowByte = SPI_Exchange8bit(0xFF); //Read the second byte
    while (!DREQ_GetValue()); //Wait after command is complete

    XCS_SetHigh(); //Deselect CS

    UINT16 resultValue = highByte << 8;
    resultValue = resultValue | lowByte;
    return resultValue;

  Read 16-bit value from addr.
UINT16 readRegister16(UINT16 addr) {
    writeRegister16(SCI_WRAMADDR, addr);
    return readRegister(SCI_WRAM);

void reset() {
    // on reset set SPI at slowest
    XCS_SetHigh(); //Deselect CS
    XDCS_SetHigh(); //Deselect DCS

    XRESET_SetLow(); // reset
    SPI_Exchange8bit(0xFF); // dummy byte
    XRESET_SetHigh(); // back from reset

    //status of the VS1053 ?
    UINT16 status = readRegister(SCI_STATUS);
    // 1001, 1011, 1011, 1003, 1053, 1033, 1063, 1103
    if (((status >> 4) & 15) != 4) {
        // something wrong, loop for debug
        while (1);

    // volume(20 = -10dB
    writeRegister(SCI_VOL, 20, 20);
    int volValue = readRegister(SCI_VOL);
    if ((volValue >> 8) != 20 && (volValue & 0xFF) != 20) {
        // something wrong, loop for debug
        while (1);

    writeRegister16(SCI_MODE, SM_SDINEW | SM_TESTS | SM_RESET);

    /* A quick sanity check: write to two registers, then test if we
     get the same results. Note that if you use a too high SPI
     speed, the MSB is the most likely to fail when read again. */
    writeRegister16(SCI_AICTRL1, 0xABAD);
    writeRegister16(SCI_AICTRL2, 0x7E57);
    UINT16 SCI_AICTRL1_V = readRegister(SCI_AICTRL1);
    UINT16 SCI_AICTRL2_V = readRegister(SCI_AICTRL2);
    if (SCI_AICTRL1_V != 0xABAD || SCI_AICTRL2_V != 0x7E57) {
        // something wrong, loop for debug
        while (1);
    writeRegister16(SCI_AICTRL1, 0);
    writeRegister16(SCI_AICTRL2, 0);

    // current clock (for debug)
    UINT16 clock = readRegister(SCI_CLOCKF);

    /* Set the clock. Until this point we need to run SPI slow so that
     we do not exceed the maximum speeds mentioned in
     Chapter SPI Timing Diagram in the Datasheet. */
    // Adafruit uses 12.288 MHz (default)
    // SC_MULT 3.5 & SC_ADD 1x (9.6.4 SCI_CLOCKF (RW))
    writeRegister16(SCI_CLOCKF, SC_MULT_53_35X | SC_ADD_53_10X);

    // clock (for debug)
    clock = readRegister(SCI_CLOCKF);

void play(UINT8* data, UINT16 len) {
    UINT8 *p;
    UINT16 readEndFillByte;
    UINT16 i, j, m, endFillByte;
    readEndFillByte = len / 2;
    p = &data[0]; // Point "p" to the beginning of array
    while (i < len) {
        // 10.5.1 Playing a Whole File
        //1. Send an audio file to VS1053b
        while (!DREQ_GetValue()) {
            //DREQ is low while the receive buffer is full
            //You can do something else here, the bus is free...
            //Maybe set the volume or whatever...

        //Once DREQ is released (high) we can now send 32 bytes of data
        XDCS_SetLow(); //Select Data
        m = min(32, len - i);
        for (j = 0; j < m; j++) {
            SPI_Exchange8bit(*p++); // Send SPI byte
        i += j;
        XDCS_SetHigh(); //Deselect Data
        if (i > readEndFillByte) {
            // 2. Read extra parameter value endFillByte (Chapter 10.11)
            UINT16 par = PAR_END_FILL_BYTE;
            endFillByte = readRegister16(par);
            readEndFillByte = len + 1;
    // 3. Send at least 2052 bytes of endFillByte[7:0].
    for (i = 0; i < 65; i++) {
        for (j = 0; j < 16; j++) {
            while (!DREQ_GetValue()); // wait here until DREQ is high again

    //4. Set SCI_MODE bit SM_CANCEL.
    UINT16 sciMode_V = readRegister(SCI_MODE);
    writeRegister16(SCI_MODE, sciMode_V | SM_CANCEL);

    // 5. Send at least 32 bytes of endFillByte[7:0]
    for (j = 0; j < 16; j++) {
        while (!DREQ_GetValue()); // wait here until DREQ is high again

    // 6.A) Read SCI_MODE. If SM_CANCEL is still set, go to 5. 
    i = 0;
    sciMode_V = readRegister(SCI_MODE);
    while (((sciMode_V & SM_CANCEL) == SM_CANCEL) && i < 64) {
        for (j = 0; j < 16; j++) {
            while (!DREQ_GetValue()); // wait here until DREQ is high again
        sciMode_V = readRegister(SCI_MODE);
    while (!DREQ_GetValue());

    // 6.B) If SM_CANCEL hasn't cleared after sending 2048 bytes, do a software 
    //      reset (this should be extremely rare).
    if ((readRegister(SCI_MODE) & SM_CANCEL) == SM_CANCEL) {

    // 7. The song has now been successfully sent. HDAT0 and HDAT1 should now both
    //    contain 0 to indicate that no format is being decoded. Return to 1.
    UINT16 HDAT0_V, HDAT1_V;
    HDAT0_V = readRegister(SCI_HDAT0);
    HDAT1_V = readRegister(SCI_HDAT1);
    if (HDAT0_V != 0 || HDAT1_V != 0) {
        // something wrong, loop
        while (1);

void sayHello() {
    play(HelloMP3, sizeof (HelloMP3));

int main(int argc, char** argv) {

    // SDCARD share SPI with VS1053
    while (1) {

User avatar
VLSI Staff
Posts: 2780
Joined: Tue 2010-06-22 13:43

Re: VS1053 & PIC24

Post by Panu » Thu 2016-12-08 22:15


Great that it's working now!

Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Posts: 8
Joined: Sat 2016-12-03 15:38

Re: VS1053 & PIC24

Post by almen_80 » Fri 2016-12-09 9:54

Hi Panu,

i have got a last question. The endFileByte returns as unsigned int from registry. Rethinking about it I suppose that the endFileByte is the lower byte. I’m right in my assumption or should both bytes (L & H) be transfered?

Thanks in advance!

PS: based on the example:
memset(playBuf, endFillByte, sizeof(playBuf));


void *memset(void *str, int c, size_t n)
str -- This is a pointer to the block of memory to fill.
c -- This is the value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.
n -- This is the number of bytes to be set to the value.

User avatar
VLSI Staff
Posts: 1749
Joined: Thu 2010-07-15 16:04

Re: VS1053 & PIC24

Post by pasi » Fri 2016-12-09 16:29

endFillByte is the lower 8 bits of the 16-bit variable. So, if your memset() fills byte arrays, it should be working correctly.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

Post Reply