aboutsummaryrefslogtreecommitdiff
path: root/src/inc/spi/dev/audio_vs1011.c
blob: ad44654fd063768e4a518a8f707790452b8b55df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include "audio_vs1011.h"
/// inline void audio_vs1011_setVolume(unsigned char left, unsigned char right)
/// { audio_vs1011_cmd(SCI_VOL, left, right); }

void audio_vs1011_init()
{
  // [initialize pins and ports]
  DDRC  |= ((1<<PC1) | (1<<PC2) | (1<<PC4)); // XCS/XDCS/RESET
  DDRC  &= ~(1<<PC3); // DREQ
  //DDRA  |=  (1<<PA6); // activate O-Port A6 as [XCS]
  //DDRC  |=  (1<<PC6); // activate O-Port C6 as [XDCS]
  //DDRD  |=  (1<<PD6); // activate O-Port D6 as [RESET]
  //DDRD  &= ~(1<<PD5); // activate I-Port D5 as [DREQ]


  // pins...
  /// PORTA |= (1<<PA6);
  /// PORTC |= (1<<PC6);
  PORTC |= (1<<PC3);        // enable pullup resistor for [DREQ]
  audio_vs1011_exit_xcs();  // activate XCS: deactivate vs1011-cmd-line
  audio_vs1011_exit_xdcs(); // activate XDCS: deactivate vs1011-data-line

  // [reset vs1011]
  // this ensures, that it finds XCS and XDCS in proper state (see below)
  /// PORTD &= ~(1<<PD6); // <reset>
  // Wait for at least 10 ms after startup (required!!)
  // then make GPIO an output signal and set it to 1...
  /// _delay_ms(20);
  PORTC |= (1<<PC4);  // </reset>
  /// _delay_ms(20);

  // wait until DREQ is set- so chip has rebooted from reset...
  wait4dreq();

  // [set vs1011 to 'new-mode']
  // where xdcs is driven low, before you want to send mp3-data or test-bits
  // where xcs is driven low to send SCI-commands.
  // and both together may not been activated, why we started with resetting
  // after having configured those output-ports.
  audio_vs1011_cmd(SCI_MODE, (SM_SDINEW | SM_TESTS));

  // [set clock-frequency...]
  // formular:
  //     32768{if clock doubler}
  //   + (F_CRYSTAL{crystals frequency in Hz} / 2000{const})
  //   = 0x9770 for a 12MHz-crystal (with clock-doubler), so send:
  /// audio_vs1011_cmd(SCI_CLOCKF, 0x98, 0x00);
  /// stdout_put_uint(uart_putc, ((F_CPU / 2000) | SC_CLK2X));
  /// stdout_put_string(uart_putc, "\t< clock freq for vs1011\n");

  audio_vs1011_cmd(SCI_CLOCKF, ((F_CPU / 2000) | SC_CLK2X));
  audio_vs1011_cmd(SCI_AUDATA, 44100);

  /*
  spi_setspeed(SPICLK_FAST);
  int q;
  for(q=0; q<=30000; q++)
    spi_putc(0x00);
  spi_setspeed(SPICLK_DEFAULT);
  // wait for at least 11000 clock cycles...
  */

  // wait until DREQ is set- so chip has rebooted from reset...
  wait4dreq();


  /// spi_putc(0xFF);

  audio_vs1011_setVolume(1, 1); // left and right both to 100%=0xFF
  /// _delay_ms(250);

  /// stdout_put_string(uart_putc, "clock frequency set!\n");
}


void audio_vs1011_setVolume(const unsigned char left, const unsigned char right)
{
  //uint16_t volume = right + (256 * left);
  /// stdout_put_uint(uart_putc, volume);
  /// stdout_put_string(uart_putc, "\t< new volume for vs1011\n");
  audio_vs1011_cmd(SCI_VOL, ((uint16_t) right) + ((uint16_t) left * 256));
}

void audio_vs1011_test_volume()
{
  audio_vs1011_setVolume(0, 0); // left and right to 0%=0x00 -> standby
  _delay_ms(250);
  audio_vs1011_setVolume(255, 255); // left and right both to 100%=0xFF
  _delay_ms(250);
}

void audio_vs1011_test_sine()
{
  static const unsigned char sinetest[] = {0x53, 0xEF, 0x6E, 0x30, 0x0, 0x0, 0x0, 0x0};
  static const unsigned char testexit[] = {'E', 'x', 'i', 't', 0x0, 0x0, 0x0, 0x0};

  /// audio_vs1011_setVolume(255, 255); // left and right both to 100%=0xFF
  /// stdout_put_string(uart_putc, "activating sine-test...\n");
  audio_vs1011_dat(sinetest, sizeof(sinetest));
  _delay_ms(250);

  /// stdout_put_string(uart_putc, "deactivating sine-test...\n");
  audio_vs1011_dat(testexit, sizeof(testexit));
  _delay_ms(250);
  /// audio_vs1011_setVolume(255, 255); // left and right both to 100%=0xFF
}

/*
void audio_vs1011_test_eeprom()
{
  unsigned char block[512];
  eeprom_read_block((void*) &block, (const void*) 0, 512);

  int i,q;
  for(i=0; i<512; i+=32)
  {
    audio_vs1011_enable();
    loop_until_bit_is_set(PIND, PD5);
    for(q=0; q<32; q++)
      spi_putc(block[i+q]);
    audio_vs1011_disable();
 }
  loop_until_bit_is_set(PIND, PD5);
 _delay_ms(500);
}
*/

void audio_vs1011_dat(const unsigned char* dat, const unsigned char size)
{
  audio_vs1011_enable();
  unsigned char i;
  for(i=0; i<size; i++)
    spi_putc(dat[i]);
  audio_vs1011_disable();
}


/*
unsigned char audio_vs1011_stream(unsigned char (*readfn)())
{
  audio_vs1011_enable();
  register unsigned char i;
  for(i=0; i<32; i++)
    spi_putc(readfn());
  audio_vs1011_disable();
  audio_vs1011_waitDREQ();
  return 32;
}*/




void audio_vs1011_cmd(const unsigned char cmd, uint16_t dat)
{
  loop_until_bit_is_set(PIND, PD5);
  /// audio_vs1011_enable();
  //PORTA &= ~(1<<PA6); // <XCS>
  audio_vs1011_init_xcs();
  spi_putc(VS_WRITE);
  spi_putc(cmd);
  spi_putc((dat >> 8) & 0xFF);
  spi_putc((dat >> 0) & 0xFF);
  //PORTA |=  (1<<PA6); // </XCS>
  audio_vs1011_exit_xcs();
  spi_putc(0);
  spi_putc(0);
  spi_putc(0);
  spi_putc(0);
  /// audio_vs1011_disable();
  /// _delay_ms(1);       // << wait to make sure vs1011 got the message
  _delay_ms(5);
  loop_until_bit_is_set(PIND, PD5); // << wait for DREQ to become ready again
}
..