1 #include <exec/types.h>
2 #include <exec/memory.h>
4 #include <libraries/dos.h>
6 #include <devices/audio.h>
8 #include <proto/exec.h>
14 #include "../../a314device/a314.h"
15 #include "../../a314device/proto_a314.h"
17 #include <clib/alib_protos.h>
19 #define SERVICE_NAME "piaudio"
22 #define BUFFER_LEN_MS 50
23 #define SAMPLES (FREQ * BUFFER_LEN_MS / 1000)
30 #define LEFT_CHAN_MASK (L0 | L1)
31 #define RIGHT_CHAN_MASK (R0 | R1)
36 struct MsgPort *sync_mp = NULL;
37 struct MsgPort *async_mp = NULL;
39 struct A314_IORequest *sync_a314_req = NULL;
40 struct A314_IORequest *write_a314_req = NULL;
42 struct Library *A314Base;
44 char *audio_buffers[4] = { NULL, NULL, NULL, NULL };
46 struct IOAudio *sync_audio_req = NULL;
47 struct IOAudio *async_audio_req[4] = { NULL, NULL, NULL, NULL };
49 ULONG allocated_channels;
51 BOOL a314_device_open = FALSE;
52 BOOL audio_device_open = FALSE;
53 BOOL stream_open = FALSE;
54 BOOL pending_a314_write = FALSE;
60 void start_a314_cmd(struct MsgPort *reply_port, struct A314_IORequest *ior, UWORD cmd, char *buffer, int length)
62 ior->a314_Request.io_Message.mn_ReplyPort = reply_port;
63 ior->a314_Request.io_Command = cmd;
64 ior->a314_Request.io_Error = 0;
65 ior->a314_Socket = socket;
66 ior->a314_Buffer = buffer;
67 ior->a314_Length = length;
68 SendIO((struct IORequest *)ior);
71 BYTE a314_connect(char *name)
74 start_a314_cmd(sync_mp, sync_a314_req, A314_CONNECT, name, strlen(name));
75 Wait(1L << sync_mp->mp_SigBit);
77 return sync_a314_req->a314_Request.io_Error;
80 BYTE a314_write(char *buffer, int length)
82 start_a314_cmd(sync_mp, sync_a314_req, A314_WRITE, buffer, length);
83 Wait(1L << sync_mp->mp_SigBit);
85 return sync_a314_req->a314_Request.io_Error;
90 start_a314_cmd(sync_mp, sync_a314_req, A314_EOS, NULL, 0);
91 Wait(1L << sync_mp->mp_SigBit);
93 return sync_a314_req->a314_Request.io_Error;
98 start_a314_cmd(sync_mp, sync_a314_req, A314_RESET, NULL, 0);
99 Wait(1L << sync_mp->mp_SigBit);
101 return sync_a314_req->a314_Request.io_Error;
104 void start_a314_write(char *buffer, int length)
106 start_a314_cmd(async_mp, write_a314_req, A314_WRITE, buffer, length);
107 pending_a314_write = TRUE;
110 void submit_async_audio_req(int index)
112 ULONG mask = ((index & 1) == LEFT) ? LEFT_CHAN_MASK : RIGHT_CHAN_MASK;
113 ULONG unit = allocated_channels & mask;
115 async_audio_req[index]->ioa_Request.io_Message.mn_ReplyPort = async_mp;
116 async_audio_req[index]->ioa_Request.io_Command = CMD_WRITE;
117 async_audio_req[index]->ioa_Request.io_Flags = ADIOF_PERVOL;
118 async_audio_req[index]->ioa_Request.io_Unit = (void*)unit;
119 async_audio_req[index]->ioa_Data = audio_buffers[index];
120 async_audio_req[index]->ioa_Length = SAMPLES;
121 async_audio_req[index]->ioa_Period = 197;
122 async_audio_req[index]->ioa_Volume = 64;
123 async_audio_req[index]->ioa_Cycles = 1;
124 BeginIO((struct IORequest *)async_audio_req[index]);
129 SetTaskPri(FindTask(NULL), 50);
131 sync_mp = CreatePort(NULL, 0);
134 printf("Unable to create sync reply message port\n");
138 async_mp = CreatePort(NULL, 0);
141 printf("Unable to create async reply message port\n");
145 sync_a314_req = (struct A314_IORequest *)CreateExtIO(sync_mp, sizeof(struct A314_IORequest));
146 write_a314_req = (struct A314_IORequest *)CreateExtIO(sync_mp, sizeof(struct A314_IORequest));
147 if (!sync_a314_req || !write_a314_req)
149 printf("Unable to create A314_IORequest\n");
153 if (OpenDevice(A314_NAME, 0, (struct IORequest *)sync_a314_req, 0))
155 printf("Unable to open a314.device\n");
159 a314_device_open = TRUE;
161 A314Base = &(sync_a314_req->a314_Request.io_Device->dd_Library);
163 memcpy(write_a314_req, sync_a314_req, sizeof(struct A314_IORequest));
165 audio_buffers[0] = AllocMem(SAMPLES * 2, MEMF_FAST | MEMF_CHIP | MEMF_CLEAR);
166 audio_buffers[2] = AllocMem(SAMPLES * 2, MEMF_FAST | MEMF_CHIP | MEMF_CLEAR);
167 if (!audio_buffers[0] || !audio_buffers[2])
169 printf("Unable to allocate audio buffers in A314 chip memory\n");
173 audio_buffers[1] = audio_buffers[0] + SAMPLES;
174 audio_buffers[3] = audio_buffers[2] + SAMPLES;
176 sync_audio_req = (struct IOAudio *)CreateExtIO(sync_mp, sizeof(struct IOAudio));
179 printf("Unable to allocate sync audio request\n");
184 for (i = 0; i < 4; i++)
186 async_audio_req[i] = AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC);
187 if (!async_audio_req[i])
189 printf("Unable to allocate async audio request\n");
194 UBYTE which_channels[] = { L0 | R0, L0 | R1, L1 | R0, L1 | R1 };
196 sync_audio_req->ioa_Request.io_Message.mn_ReplyPort = sync_mp;
197 sync_audio_req->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
198 sync_audio_req->ioa_Request.io_Command = ADCMD_ALLOCATE;
199 sync_audio_req->ioa_Request.io_Flags = ADIOF_NOWAIT;
200 sync_audio_req->ioa_AllocKey = 0;
201 sync_audio_req->ioa_Data = which_channels;
202 sync_audio_req->ioa_Length = sizeof(which_channels);
204 if (OpenDevice(AUDIONAME, 0, (struct IORequest *)sync_audio_req, 0))
206 printf("Unable to open audio.device\n");
210 audio_device_open = TRUE;
212 allocated_channels = (ULONG)sync_audio_req->ioa_Request.io_Unit;
214 for (i = 0; i < 4; i++)
215 memcpy(async_audio_req[i], sync_audio_req, sizeof(struct IOAudio));
217 if (a314_connect(SERVICE_NAME) != A314_CONNECT_OK)
219 printf("Unable to connect to piaudio service\n");
225 ULONG *buf_ptrs = (ULONG *)awbuf;
226 buf_ptrs[0] = TranslateAddressA314(audio_buffers[0]);
227 buf_ptrs[1] = TranslateAddressA314(audio_buffers[2]);
228 if (a314_write(awbuf, 8) != A314_WRITE_OK)
230 printf("Unable to write buffer pointers\n");
234 printf("PiAudio started, allocated channels: L%d, R%d\n",
235 (allocated_channels & LEFT_CHAN_MASK) == L0 ? 0 : 1,
236 (allocated_channels & RIGHT_CHAN_MASK) == R0 ? 0 : 1);
238 sync_audio_req->ioa_Request.io_Command = CMD_STOP;
239 DoIO((struct IORequest *)sync_audio_req);
241 submit_async_audio_req(back_index + LEFT);
242 submit_async_audio_req(back_index + RIGHT);
244 sync_audio_req->ioa_Request.io_Command = CMD_START;
245 DoIO((struct IORequest *)sync_audio_req);
247 int pending_audio_reqs = 2;
249 ULONG portsig = 1L << async_mp->mp_SigBit;
251 printf("Press ctrl-c to exit...\n");
255 if (pending_audio_reqs <= 2)
259 submit_async_audio_req(back_index + LEFT);
260 submit_async_audio_req(back_index + RIGHT);
262 pending_audio_reqs += 2;
264 if (!pending_a314_write)
266 awbuf[0] = back_index == 0 ? 0 : 1;
267 start_a314_write(awbuf, 1);
271 ULONG signal = Wait(SIGBREAKF_CTRL_C | portsig);
273 if (signal & SIGBREAKF_CTRL_C)
275 else if (signal & portsig)
278 while (msg = GetMsg(async_mp))
280 if (msg == (struct Message *)write_a314_req)
282 if (write_a314_req->a314_Request.io_Error == A314_WRITE_OK)
283 pending_a314_write = FALSE;
288 pending_audio_reqs--;
296 if (audio_device_open)
297 CloseDevice((struct IORequest *)sync_audio_req);
298 for (i = 3; i >= 0; i--)
299 if (async_audio_req[i])
300 FreeMem(async_audio_req[i], sizeof(struct IOAudio));
302 DeleteExtIO((struct IORequest *)sync_audio_req);
303 if (audio_buffers[2])
304 FreeMem(audio_buffers[2], SAMPLES * 2);
305 if (audio_buffers[0])
306 FreeMem(audio_buffers[0], SAMPLES * 2);
307 if (a314_device_open)
308 CloseDevice((struct IORequest *)sync_a314_req);
310 DeleteExtIO((struct IORequest *)write_a314_req);
312 DeleteExtIO((struct IORequest *)sync_a314_req);
314 DeletePort(async_mp);