1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - library - dsp
3 File: dsp_byteaccess.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-17#$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <twl.h>
19 #include <twl/dsp.h>
20 #include <twl/dsp/common/byteaccess.h>
21
22
23 /*---------------------------------------------------------------------------*/
24 /* Functions */
25
26 /*---------------------------------------------------------------------------*
27 Name: DSP_Load16
28
29 Description: Reads 16 bits from the DSP data memory space.
30
31 Arguments: offset: Transfer source DSP address (in bytes)
32
33 Returns: The 16-bit data that was read.
34 *---------------------------------------------------------------------------*/
DSP_Load16(DSPAddrInARM offset)35 u16 DSP_Load16(DSPAddrInARM offset)
36 {
37 OSIntrMode cpsr = OS_DisableInterrupts();
38 u16 result = DSP_LoadWord(DSP_WORD_TO_DSP(offset));
39 if ((offset & 1) != 0)
40 {
41 result = (u16)((DSP_LoadWord(DSP_WORD_TO_DSP(offset + 2)) << (16 - 8)) | (result >> 8));
42 }
43 (void)OS_RestoreInterrupts(cpsr);
44 return result;
45 }
46
47 /*---------------------------------------------------------------------------*
48 Name: DSP_Load32
49
50 Description: Reads 32 bits from the DSP data memory space.
51
52 Arguments: offset: Transfer source DSP address (in bytes)
53
54 Returns: The 32-bit data that was read.
55 *---------------------------------------------------------------------------*/
DSP_Load32(DSPAddrInARM offset)56 u32 DSP_Load32(DSPAddrInARM offset)
57 {
58 u32 result = (u32)((DSP_LoadWord(DSP_WORD_TO_DSP(offset + 0)) << 0) |
59 (DSP_LoadWord(DSP_WORD_TO_DSP(offset + 2)) << 16));
60 if ((offset & 1) != 0)
61 {
62 result = (u32)((DSP_LoadWord(DSP_WORD_TO_DSP(offset + 4)) << (32 - 8)) | (result >> 8));
63 }
64 return result;
65 }
66
67 /*---------------------------------------------------------------------------*
68 Name: DSP_LoadData
69
70 Description: Reads an arbitrary length of data from the DSP data memory space.
71
72 Arguments: offset: Transfer source DSP address (in bytes)
73 buffer: Transfer destination buffer
74 length: Size of the transmission
75
76 Returns: None.
77 *---------------------------------------------------------------------------*/
DSP_LoadData(DSPAddrInARM offset,void * buffer,u32 length)78 void DSP_LoadData(DSPAddrInARM offset, void *buffer, u32 length)
79 {
80 if (length > 0)
81 {
82 // First, align leading end of transfer source.
83 if ((offset & 1) != 0)
84 {
85 MI_StoreLE8(buffer, DSP_Load8(offset));
86 buffer = (u8 *)buffer + 1;
87 offset += 1;
88 length -= 1;
89 }
90 // If the buffer is aligned, transmit the word as is; if not aligned, repeat word tranmissions repeatedly, although this is inefficient.
91 //
92 // (This support can be implemented in the DSP_RecvFifo function, right?)
93 if (((u32)buffer & 1) == 0)
94 {
95 u32 aligned = (u32)(length & ~1);
96 if (aligned > 0)
97 {
98 OSIntrMode cpsr = OS_DisableInterrupts();
99 DSP_RecvFifo(DSP_FIFO_MEMSEL_DATA,
100 (u16*)buffer,
101 DSP_WORD_TO_DSP(offset),
102 DSP_WORD_TO_DSP(aligned));
103 reg_DSP_PCFG &= ~(REG_DSP_PCFG_DRS_MASK | REG_DSP_PCFG_AIM_MASK);
104 (void)OS_RestoreInterrupts(cpsr);
105 buffer = (u8 *)buffer + aligned;
106 offset += aligned;
107 length -= aligned;
108 }
109 }
110 else
111 {
112 while (length >= 2)
113 {
114 MI_StoreLE16(buffer, DSP_LoadWord(DSP_WORD_TO_DSP(offset)));
115 buffer = (u8 *)buffer + 2;
116 offset += 2;
117 length -= 2;
118 }
119 }
120 // If necessary, load the end
121 if (length > 0)
122 {
123 MI_StoreLE8(buffer, DSP_Load8(offset));
124 }
125 }
126 }
127
128 /*---------------------------------------------------------------------------*
129 Name: DSP_Store8
130
131 Description: Writes 8 bits to the DSP data memory space.
132
133 Arguments: offset: Transfer source DSP address (in bytes)
134 value: The 8-bit value to write
135
136 Returns: None.
137 *---------------------------------------------------------------------------*/
DSP_Store8(DSPAddrInARM offset,u8 value)138 void DSP_Store8(DSPAddrInARM offset, u8 value)
139 {
140 if ((offset & 1) == 0)
141 {
142 u16 tmp = DSP_LoadWord(DSP_WORD_TO_DSP(offset));
143 tmp = (u16)((tmp & 0xFF00) | ((value << 0) & 0x00FF));
144 DSP_StoreWord(DSP_WORD_TO_DSP(offset), tmp);
145 }
146 else
147 {
148 u16 tmp = DSP_LoadWord(DSP_WORD_TO_DSP(offset));
149 tmp = (u16)((tmp & 0x00FF) | ((value << 8) & 0xFF00));
150 DSP_StoreWord(DSP_WORD_TO_DSP(offset), tmp);
151 }
152 }
153
154 /*---------------------------------------------------------------------------*
155 Name: DSP_Store16
156
157 Description: Writes 16 bits to the DSP data memory space.
158
159 Arguments: offset: Transfer source DSP address (in bytes)
160 value: The 16-bit value to write
161
162 Returns: None.
163 *---------------------------------------------------------------------------*/
DSP_Store16(DSPAddrInARM offset,u16 value)164 void DSP_Store16(DSPAddrInARM offset, u16 value)
165 {
166 if ((offset & 1) == 0)
167 {
168 DSP_StoreWord(DSP_WORD_TO_DSP(offset), value);
169 }
170 else
171 {
172 DSP_Store8(offset + 0, (u8)(value >> 0));
173 DSP_Store8(offset + 1, (u8)(value >> 8));
174 }
175 }
176
177 /*---------------------------------------------------------------------------*
178 Name: DSP_Store32
179
180 Description: Writes 32 bits to the DSP data memory space.
181
182 Arguments: offset: Transfer source DSP address (in bytes)
183 value: The 32-bit value to write
184
185 Returns: None.
186 *---------------------------------------------------------------------------*/
DSP_Store32(DSPAddrInARM offset,u32 value)187 void DSP_Store32(DSPAddrInARM offset, u32 value)
188 {
189 if ((offset & 1) == 0)
190 {
191 DSP_StoreWord(DSP_WORD_TO_DSP(offset + 0), (u16)(value >> 0));
192 DSP_StoreWord(DSP_WORD_TO_DSP(offset + 2), (u16)(value >> 16));
193 }
194 else
195 {
196 DSP_Store8(offset + 0, (u8)(value >> 0));
197 DSP_StoreWord(DSP_WORD_TO_DSP(offset + 1), (u16)(value >> 8));
198 DSP_Store8(offset + 3, (u8)(value >> 24));
199 }
200 }
201
202 /*---------------------------------------------------------------------------*
203 Name: DSP_StoreData
204
205 Description: Writes arbitrary length data to the DSP data memory space.
206
207 Arguments: offset: Transfer source DSP address (in bytes)
208 buffer: Transfer source buffer
209 length: Size of the transmission
210
211 Returns: None.
212 *---------------------------------------------------------------------------*/
DSP_StoreData(DSPAddrInARM offset,const void * buffer,u32 length)213 void DSP_StoreData(DSPAddrInARM offset, const void *buffer, u32 length)
214 {
215 if (length > 0)
216 {
217 // First, align leading end of transfer destination
218 if ((offset & 1) != 0)
219 {
220 DSP_Store8(offset, MI_LoadLE8(buffer));
221 buffer = (const u8 *)buffer + 1;
222 offset += 1;
223 length -= 1;
224 }
225 // If the buffer is aligned, transmit the word as is; if not aligned, repeat word tranmissions repeatedly, although this is inefficient.
226 //
227 // (This support can be implemented in the DSP_SendFifo function, right?)
228 if (((u32)buffer & 1) == 0)
229 {
230 u32 aligned = (u32)(length & ~1);
231 if (aligned > 0)
232 {
233 OSIntrMode cpsr = OS_DisableInterrupts();
234 DSP_SendFifo(DSP_FIFO_MEMSEL_DATA,
235 DSP_WORD_TO_DSP(offset),
236 (const u16 *)buffer,
237 DSP_WORD_TO_DSP(aligned));
238 // reg_DSP_PCFG &= ~(REG_DSP_PCFG_DRS_MASK | REG_DSP_PCFG_AIM_MASK);
239 (void)OS_RestoreInterrupts(cpsr);
240 buffer = (const u8 *)buffer + aligned;
241 offset += aligned;
242 length -= aligned;
243 }
244 }
245 else
246 {
247 while (length >= 2)
248 {
249 DSP_StoreWord(DSP_WORD_TO_DSP(offset), MI_LoadLE16(buffer));
250 buffer = (const u8 *)buffer + 2;
251 offset += 2;
252 length -= 2;
253 }
254 }
255 // If necessary, write the end
256 if (length > 0)
257 {
258 DSP_Store8(offset, MI_LoadLE8(buffer));
259 }
260 }
261 }
262