-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathisd.c
266 lines (260 loc) · 6.49 KB
/
isd.c
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#include "isd.h"
const isd_cmd_t pu = {0x01,2,0};
const isd_cmd_t stop = {0x02,2,0};
const isd_cmd_t reset = {0x03,2,0};
const isd_cmd_t clr_int = {0x04,2,0};
const isd_cmd_t rd_status = {0x05,3,0};
const isd_cmd_t rd_play_ptr ={0x06,4,0};
const isd_cmd_t pd = {0x07,2,0};
const isd_cmd_t rd_rec_ptr = {0x08,4,0};
const isd_cmd_t devid = {0x09,3,0};
const isd_cmd_t play = {0x40,2,0};
const isd_cmd_t rec = {0x41,2,0};
const isd_cmd_t erase = {0x42,2,0};
const isd_cmd_t g_erase = {0x43,2,0};
const isd_cmd_t rd_apc = {0x44,4,0};
const isd_cmd_t wr_apc1 = {0x45,3,1};
const isd_cmd_t wr_apc2 = {0x65,3,1};
const isd_cmd_t wr_nvcfg = {0x46,2,0};
const isd_cmd_t ld_nvcfg = {0x47,2,0};
const isd_cmd_t fwd = {0x48,2,0};
const isd_cmd_t chk_mem = {0x49,2,0};
const isd_cmd_t extclk = {0x4a,2,0};
const isd_cmd_t set_play = {0x80,7,2};
const isd_cmd_t set_rec = {0x81,7,2};
const isd_cmd_t set_erase = {0x82,7,2};
//initialize isd module
void init_isd()
{
isd_cmd_len = 0;
isd_rx_index = 0;
isd_tx_index = 0;
//master mode, 3 pin(SS controlled via software), synchronous
UCB0CTL0 = UCCKPL | UCMST | UCMODE_0 | UCSYNC;
UCB0CTL1 = UCSSEL_2 | UCSWRST;
//ucbclk = clk/512 (2KHz)
UCB0BR0 = 0x00;
UCB0BR1 = 0x01;
set_gpio_p1_high(GPIO_USCI_SS);
//disable reset
UCB0CTL1 &= ~(UCSWRST);
//power up for SPI mode
isd_transmit_validate(&pu,0,0);
//assign memory space based on capacity of the device
isd_transmit(&devid,0,0);
unsigned int id = isd_read(2)>>3;
//isd_transmit(&rd_status,0,0);
//isd_read(0);
switch(id) {
case 0b11100:
{
isd_mem_max = ISD_MEM_17240;
break;
}
case 0b11101:
{
isd_mem_max = ISD_MEM_17210;
break;
}
case 0b11110:
{
isd_mem_max = ISD_MEM_17180;
break;
}
case 0b11000:
{
isd_mem_max = ISD_MEM_17150;
break;
}
case 0b11001:
{
isd_mem_max = ISD_MEM_17120;
break;
}
case 0b11010:
{
isd_mem_max = ISD_MEM_1790;
break;
}
case 0b10100:
{
isd_mem_max = ISD_MEM_1760;
break;
}
case 0b10101:
{
isd_mem_max = ISD_MEM_1750;
break;
}
case 0b10110:
{
isd_mem_max = ISD_MEM_1740;
break;
}
case 0b10000:
{
isd_mem_max = ISD_MEM_1730;
break;
}
default:
{
isd_mem_max = ISD_MEM_1730;
halt();
}
}//switch
isd_mem_msg = (isd_mem_max - ISD_MEM_BEGIN)/4;
isd_ptr[0] = ISD_MEM_BEGIN;
isd_ptr[1] = ISD_MEM_BEGIN+isd_mem_msg;
isd_ptr[2] = ISD_MEM_BEGIN+(isd_mem_msg*2);
isd_ptr[3] = ISD_MEM_BEGIN+(isd_mem_msg*3);
//set device to end at EOM.
//get current APC settings
isd_transmit(&rd_apc,0,0);
//put APC register into an int
unsigned int apc = isd_read(3) | ISD_EOM_ENABLE;
apc = apc<<8;
apc |= isd_read(2);
isd_transmit(&clr_int,0,0);
isd_wait_ready();
isd_transmit(&wr_apc2,apc,0);
isd_wait_ready();
}
//wait until isd can accept another command
void isd_wait_ready()
{
do
{
isd_transmit(&rd_status,0,0);
} while(!(isd_read(2)&ISD_RDY));
}
//send a signal and ensure it was read correctly.
void isd_transmit_validate(const isd_cmd_t* command, unsigned int data, unsigned int data2)
{
do
{
isd_transmit(command,data,data2);
isd_transmit(&rd_status,0,0);
} while (isd_read(0)&ISD_CMD_ERR);
}
//returns true if the isd is currently recording
int isd_is_recording()
{
isd_transmit(&rd_status,0,0);
if (isd_read(2)&ISD_REC)
return 1;
return 0;
}
//returns true if the isd is currently playing
int isd_is_playing()
{
isd_transmit(&rd_status,0,0);
if(isd_read(2)&ISD_PLAY)
return 1;
return 0;
}
//returns true if the isd found an eom
int isd_eom()
{
isd_transmit(&rd_status,0,0);
if(isd_read(0)&ISD_EOM)
return 1;
return 0;
}
//returns true if the int flag on the isd is raised
int isd_interrupt()
{
isd_transmit(&rd_status,0,0);
if(isd_read(0)&ISD_INT)
return 1;
return 0;
}
//set isd to record on an audio channel
void isd_set_rec(unsigned int audio_channel)
{
if(audio_channel > 4 || audio_channel == 0)
return;
audio_channel--;
//erase whatever's currently in memory at that location
isd_transmit(&clr_int,0,0);
isd_wait_ready();
isd_transmit_validate(&set_erase,isd_ptr[audio_channel], isd_ptr[audio_channel]+isd_mem_msg-1);
isd_wait_ready();
//record new data
isd_transmit(&clr_int,0,0);
isd_wait_ready();
isd_transmit_validate(&set_rec,isd_ptr[audio_channel], isd_ptr[audio_channel]+isd_mem_msg-1);
}
//set isd to play from an audio channel.
void isd_set_play(unsigned int audio_channel)
{
if (audio_channel > 4 || audio_channel == 0)
return;
audio_channel--;
isd_transmit(&clr_int,0,0);
isd_wait_ready();
isd_transmit_validate(&set_play,isd_ptr[audio_channel], isd_ptr[audio_channel]+isd_mem_msg-1);
}
//stop play or recording
void isd_stop()
{
isd_transmit(&clr_int,0,0);
isd_wait_ready();
isd_transmit_validate(&stop,0,0);
}
//wrapper for interrupt clear
void isd_clear_interrupt()
{
isd_transmit(&clr_int,0,0);
}
//send a command to the isd
void isd_transmit(const isd_cmd_t * command, unsigned int data, unsigned int data2)
{
while (IE2 & UCB0RXIE)
;
if (!command)
return;
unsigned int i;
for (i=0; i<7; i++)
{
isd_tx[i] = 0;
isd_rx[i] = 0;
}
isd_tx[0] = command->cmd | BIT4;
if (command->fields==1)
{
isd_tx[1] = (char)data;
isd_tx[2] = data>>8;
}
else if (command->fields==2)
{
isd_tx[2] = (char)data;
isd_tx[3] = data>>8;
isd_tx[4] = (char)data2;
isd_tx[5] = data2>>8;
}
isd_cmd_len = command->length;
isd_rx_index = 0;
isd_tx_index = 0;
//set line low
P1OUT &= ~GPIO_USCI_SS;
//begin transmission
UCB0TXBUF = isd_tx[isd_tx_index++];
//enable interrupt
IE2 |= UCB0TXIE | UCB0RXIE;
}
//read the current row address from last transmission
unsigned int isd_decode_current_row()
{
while (IE2 & UCB0RXIE)
;
unsigned int result = isd_rx[1]<<3;
result |= (isd_rx[0]&ISD_A2_0)>>5;
return result;
}
//wait until the current transmission is done then return data at index
unsigned char isd_read(unsigned int index)
{
while (IE2 & UCB0RXIE)
;
return isd_rx[index];
}