Skip to content

Instantly share code, notes, and snippets.

@mntmn
Created August 18, 2021 13:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mntmn/1e6fbdc266d599b55254c32394e47c2f to your computer and use it in GitHub Desktop.
Save mntmn/1e6fbdc266d599b55254c32394e47c2f to your computer and use it in GitHub Desktop.
#include <exec/exec.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/view.h>
#include <proto/graphics.h>
#include <clib/graphics_protos.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/utility.h>
//#include <proto/ahi.h>
#include <proto/ahi_sub.h>
#include <clib/ahi_sub_protos.h>
#include <clib/debug_protos.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
//#include "../pi-ahi-enums.h"
#include "pi-ahi.h"
#define STR(s) #s
#define XSTR(s) STR(s)
#define DEVICE_NAME "pi-ahi.audio"
#define DEVICE_DATE "(16 Aug 2021)"
#define DEVICE_ID_STRING "Pi-AHI " XSTR(DEVICE_VERSION) "." XSTR(DEVICE_REVISION) " " DEVICE_DATE
#define DEVICE_VERSION 4
#define DEVICE_REVISION 14
#define DEVICE_PRIORITY 0
struct ExecBase *SysBase;
struct UtilityBase *UtilityBase;
struct Library *AHIsubBase = NULL;
struct DosLibrary *DOSBase = NULL;
struct GfxBase *GraphicsBase = NULL;
#define AHI_DEBUGMSG 0
#define AHI_U1 0
#define AHI_U321 0
#define AHI_U322 0
#define AHI_U323 0
#define AHI_U324 0
inline void WRITESHORT(uint32_t a, uint16_t b) {
*((volatile uint16_t*)(0x400000f2)) = b;
*((volatile uint16_t*)(0x400000f0)) = 0xa;
}
inline void WRITELONG(uint32_t a, uint32_t b) {
*((volatile uint16_t*)(0x400000f2)) = b>>16;
*((volatile uint16_t*)(0x400000f2)) = b;
*((volatile uint16_t*)(0x400000f0)) = 0xa;
}
int __attribute__((no_reorder)) _start()
{
WRITESHORT(AHI_DEBUGMSG, 111);
return -1;
}
asm("romtag: \n"
" dc.w "XSTR(RTC_MATCHWORD)" \n"
" dc.l romtag \n"
" dc.l endcode \n"
" dc.b "XSTR(RTF_AUTOINIT)" \n"
" dc.b "XSTR(DEVICE_VERSION)" \n"
" dc.b "XSTR(NT_LIBRARY)" \n"
" dc.b "XSTR(DEVICE_PRIORITY)" \n"
" dc.l _device_name \n"
" dc.l _device_id_string \n"
" dc.l _auto_init_tables \n"
"endcode: \n");
const char device_name[] = DEVICE_NAME;
const char device_id_string[] = DEVICE_ID_STRING;
struct pi_ahi *pi_ahi_base = NULL;
const uint16_t freqs[] = {
4096,
8192,
11025,
22050,
44100,
48000,
};
#define debug(...)
#define debugval(...)
//#define KPrintF(...)
//#define KPrintF(a) kprintf((CONST_STRPTR)a)
//#define debug(c, v) WRITESHORT(c, v)
//#define debugmsg(...)
//#define debugbyte(...)
//#define debugshort(...)
//#define debuglong(...)
#define debugmsg(v) WRITESHORT(AHI_DEBUGMSG, v)
#define debugbyte(c, v) WRITEBYTE(c, v)
#define debugshort(c, v) WRITESHORT(c, v)
#define debuglong(c, v) WRITELONG(c, v)
static uint32_t __attribute__((used)) init (BPTR seg_list asm("a0"), struct Library *dev asm("d0"))
{
SysBase = *(struct ExecBase **)4L;
if (pi_ahi_base != NULL) {
debugmsg(101);
return 0;
}
debuglong(AHI_U321, (uint32_t)dev);
debugmsg(1);
char prefs[10] = "0";
if (prefs[0] == '0') {} // TODO: prefs?
debugmsg(103);
if(!(DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",0)))
return 0;
if(!(UtilityBase = (struct UtilityBase *)OpenLibrary((STRPTR)"utility.library",0)))
return 0;
if (!pi_ahi_base) {
debugmsg(102);
pi_ahi_base = AllocVec(sizeof(struct pi_ahi), MEMF_PUBLIC | MEMF_CLEAR);
pi_ahi_base->ahi_base = dev;
AHIsubBase = dev;
}
debugmsg(104);
return (uint32_t)dev;
}
static uint8_t* __attribute__((used)) expunge(struct Library *libbase asm("a6"))
{
debugmsg(999);
if(DOSBase) { CloseLibrary((struct Library *)DOSBase); DOSBase = NULL; }
if(UtilityBase) { CloseLibrary((struct Library *)UtilityBase); UtilityBase = NULL; }
return 0;
}
static uint8_t __attribute__((used)) null()
{
debugmsg(998);
return 0;
}
static void __attribute__((used)) open(struct Library *dev asm("a6"), struct IORequest *iotd asm("a1"), uint32_t num asm("d0"), uint32_t flags asm("d1"))
{
debugmsg(2);
debugmsg((uint32_t)dev);
if (!AHIsubBase) {
debugmsg(201);
AHIsubBase = dev;
}
iotd->io_Error = 0;
dev->lib_OpenCnt++;
}
static uint8_t* __attribute__((used)) close(struct Library *dev asm("a6"), struct IORequest *iotd asm("a1"))
{
debugmsg(3);
return 0;
}
static void __attribute__((used)) begin_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
{
debugmsg(4);
if (pi_ahi_base == NULL || io == NULL)
return;
if (!(io->io_Flags & IOF_QUICK)) {
ReplyMsg(&io->io_Message);
}
}
static uint32_t __attribute__((used)) abort_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
{
debugmsg(5);
if (!io) return IOERR_NOCMD;
io->io_Error = IOERR_ABORTED;
return IOERR_ABORTED;
}
static uint32_t __attribute__((used)) SoundFunc(struct Hook *hook asm("a0"), struct AHIAudioCtrlDrv *actrl asm("a2"), struct AHISoundMessage *chan asm("a1"))
{
debugmsg(9992);
return 0;
}
static void __attribute__((used)) PlayFunc() {
struct pi_ahi *ahi_data = pi_ahi_base;
debugmsg(21);
}
static void __attribute__((used)) MixFunc() {
struct pi_ahi *ahi_data = pi_ahi_base;
debugmsg(22);
}
#define AUDIO_BUF ((void*)0x40010000)
static void SlaveProcess()
{
struct Process *me = (struct Process *) FindTask(NULL);
struct pi_ahi *ahi_data = pi_ahi_base;
struct AHIAudioCtrlDrv *AudioCtrl = ahi_data->audioctrl;
struct DosLibrary *DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",37);
if (me) {} // TODO: Do something with me.
//ahi_data->flags &= ~(1 | 2);
ahi_data->slave_signal = AllocSignal(-1);
ahi_data->play_signal = AllocSignal(-1);
ahi_data->mix_signal = AllocSignal(-1);
ahi_data->enable_signal = AllocSignal(-1);
uint32_t signals;
if((ahi_data->slave_signal != -1) && (ahi_data->play_signal != -1) && (ahi_data->mix_signal != -1)) {
// Tell Master we're alive
Signal(ahi_data->t_master, 1L << ahi_data->master_signal);
AudioCtrl->ahiac_SoundFunc->h_Entry = (void *)SoundFunc;
for(;;) {
debugmsg(0x1000);
signals = SetSignal(0, 0); // reads the signals
if (signals & SIGBREAKF_CTRL_C) {
debugmsg(0x1001);
break;
}
if (!(signals & (1L<<ahi_data->enable_signal))) {
debugmsg(0x1002);
Wait(1L<<ahi_data->enable_signal);
}
debugmsg(0x1003);
CallHookPkt(AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL);
debugmsg(0x1004);
if (AudioCtrl->ahiac_MixerFunc) {
debugmsg(0x1005);
CallHookPkt(AudioCtrl->ahiac_MixerFunc, AudioCtrl, AUDIO_BUF);
debugmsg(0x1006);
} else {
debugmsg(0x1007);
}
uint32_t samples = AudioCtrl->ahiac_BuffSamples*(AudioCtrl->ahiac_Flags & AHIACF_STEREO ? 2 : 1);
debugmsg(0x1008);
WRITELONG(0,samples);
}
}
//ahi_data->flags &= ~(1 | 2);
debugmsg(0x9999);
Forbid();
FreeSignal(ahi_data->enable_signal); ahi_data->enable_signal = -1;
FreeSignal(ahi_data->slave_signal); ahi_data->slave_signal = -1;
FreeSignal(ahi_data->play_signal); ahi_data->play_signal = -1;
FreeSignal(ahi_data->mix_signal); ahi_data->mix_signal = -1;
ahi_data->slave_process = NULL;
Signal((struct Task *)ahi_data->t_master, 1L << ahi_data->master_signal);
// Multitaking will resume when we are dead.
debugmsg(0x999f);
}
static uint32_t __attribute__((used)) intAHIsub_AllocAudio(struct TagItem *tagList asm("a1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
debugmsg(6);
SysBase = *(struct ExecBase **)4L;
if (!DOSBase) {
DOSBase = (struct DosLibrary *)OpenLibrary((STRPTR)"dos.library",37);
}
if(!UtilityBase) {
UtilityBase = (struct UtilityBase *)OpenLibrary((STRPTR)"utility.library",37);
}
debuglong(AHI_U321, sizeof(struct pi_ahi));
debugmsg(601);
if((AudioCtrl->ahiac_DriverData = AllocVec(sizeof(struct pi_ahi), MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR)))
{
debugmsg(603);
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
ahi_data->audioctrl = AudioCtrl;
if (pi_ahi_base != ahi_data) {
pi_ahi_base = ahi_data;
}
ahi_data->ahi_base = AHIsubBase;
ahi_data->slave_signal = -1;
ahi_data->play_signal = -1;
ahi_data->enable_signal = -1;
ahi_data->mix_signal = -1;
debugmsg(604);
ahi_data->t_master = FindTask(NULL);
ahi_data->master_signal = AllocSignal(-1);
if (ahi_data->master_signal != -1) {
debuglong(AHI_U321, (uint32_t)ahi_data);
debugmsg(605);
Forbid();
if (ahi_data->slave_process = CreateNewProcTags(NP_Entry, (uint32_t)&SlaveProcess, NP_Name, (uint32_t)device_name, NP_Priority, 127, TAG_DONE)) {
debugmsg(606);
ahi_data->slave_process->pr_Task.tc_UserData = AudioCtrl;
}
Permit();
debugmsg(607);
if(ahi_data->slave_process) {
debugmsg(608);
Wait(1L << ahi_data->master_signal); // Wait for slave to come alive
if(ahi_data->slave_process != NULL) {
debugmsg(609);
ahi_data->flags |= 4;
}
}
}
}
debugmsg(610);
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
ahi_data->ahi_base = AHIsubBase;
debugshort(AHI_U1, AudioCtrl->ahiac_MixFreq);
debugmsg(602);
ahi_data->mix_freq = AudioCtrl->ahiac_MixFreq;
return AHISF_KNOWSTEREO | AHISF_MIXING | AHISF_TIMING;
}
static void __attribute__((used)) intAHIsub_FreeAudio(struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
debugmsg(0x6000);
if (AudioCtrl->ahiac_DriverData) {
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
if (ahi_data->slave_process) {
Signal((struct Task *)ahi_data->slave_process, SIGBREAKF_CTRL_C);
debugmsg(0x999e);
Wait(1L << ahi_data->master_signal);
}
FreeSignal(ahi_data->master_signal);
FreeVec(AudioCtrl->ahiac_DriverData);
AudioCtrl->ahiac_DriverData = NULL;
}
}
static uint32_t __attribute__((used)) intAHIsub_Stop(uint32_t Flags asm("d0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
debugmsg(0x7000);
if (Flags & AHISF_PLAY) {
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
Signal((struct Task *)ahi_data->slave_process, SIGBREAKF_CTRL_C);
if (ahi_data->play_soft_int) {
debugmsg(0x7091);
FreeVec(ahi_data->play_soft_int); ahi_data->play_soft_int = NULL;
}
if (ahi_data->mix_soft_int) {
debugmsg(0x7092);
FreeVec(ahi_data->mix_soft_int); ahi_data->mix_soft_int = NULL;
}
debugmsg(0x7093);
for (int i = 0; i < 8; i++) {
debuglong(AHI_U321, i);
debugmsg(0x7094);
if (ahi_data->samp_buf[i]) { FreeVec(ahi_data->samp_buf[i]); ahi_data->samp_buf[i] = NULL; }
if (ahi_data->mix_buf[i]) { FreeVec(ahi_data->mix_buf[i]); ahi_data->mix_buf[i] = NULL; }
}
}
return AHIE_OK;
}
static uint32_t __attribute__((used)) intAHIsub_Start(uint32_t flags asm("d0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
debugmsg(0x8000);
intAHIsub_Stop(flags, AudioCtrl);
if (flags & AHISF_PLAY) {
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
debugshort(AHI_U1, AudioCtrl->ahiac_BuffType);
debuglong(AHI_U321, AudioCtrl->ahiac_BuffSize);
debugmsg(81);
ahi_data->play_soft_int = AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
ahi_data->mix_soft_int = AllocVec(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
if (!ahi_data->play_soft_int || !ahi_data->mix_soft_int) {
debugmsg(82);
if (ahi_data->play_soft_int) { FreeVec(ahi_data->play_soft_int); ahi_data->play_soft_int = 0; }
if (ahi_data->mix_soft_int) { FreeVec(ahi_data->mix_soft_int); ahi_data->mix_soft_int = 0; }
return AHIE_NOMEM;
}
ahi_data->buffer_type = AudioCtrl->ahiac_BuffType;
ahi_data->buffer_size = AudioCtrl->ahiac_BuffSize;
for (int i = 0; i < 8; i++) {
ahi_data->samp_buf[i] = AllocVec(512 * 4, MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
ahi_data->mix_buf[i] = AllocVec(ahi_data->buffer_size, MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR);
}
ahi_data->play_soft_int->is_Code = (void (* )())PlayFunc;
ahi_data->play_soft_int->is_Node.ln_Type = NT_INTERRUPT;
ahi_data->play_soft_int->is_Node.ln_Name = (char *)device_name;
ahi_data->play_soft_int->is_Data = AudioCtrl;
ahi_data->mix_soft_int->is_Code = (void (* )())MixFunc;
ahi_data->mix_soft_int->is_Node.ln_Type = NT_INTERRUPT;
ahi_data->mix_soft_int->is_Node.ln_Name = (char *)device_name;
ahi_data->mix_soft_int->is_Data = AudioCtrl;
Signal((struct Task *)ahi_data->slave_process, 1L << ahi_data->play_signal);
}
return AHIE_OK;
}
static uint32_t __attribute__((used)) intAHIsub_GetAttr(uint32_t attr_ asm("d0"), int32_t arg_ asm("d1"), int32_t def_ asm("d2"), struct TagItem *tagList asm("a1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2")) {
uint32_t attr = attr_;
int32_t arg = arg_, def = def_;
debugmsg(10);
debuglong(AHI_U321, attr);
debuglong(AHI_U322, arg);
debuglong(AHI_U323, def);
debugmsg(1001);
switch(attr)
{
case AHIDB_Bits:
debugmsg(1002);
return 16;
case AHIDB_Frequencies:
debugmsg(1003);
return 6;
case AHIDB_Frequency:
debugmsg(1004);
return freqs[arg];
case AHIDB_Index:
debugmsg(1005);
for (int i = 0; i < 6; i++) {
if (freqs[i] == arg)
return i;
}
return -1;
case AHIDB_Author:
debugmsg(1006);
return (int32_t) "PiStorm AHI";
case AHIDB_Copyright:
debugmsg(1007);
return (int32_t) "The PiStorms";
case AHIDB_Version:
debugmsg(1008);
return (int32_t) device_id_string;
case AHIDB_Annotation:
debugmsg(1009);
return (int32_t) "Based in part on the Toccata driver";
case AHIDB_Record:
debugmsg(1010);
return FALSE;
case AHIDB_FullDuplex:
debugmsg(1011);
return TRUE;
case AHIDB_Realtime:
debugmsg(1012);
return TRUE;
case AHIDB_MaxChannels:
debugmsg(1013);
return 16;
case AHIDB_MaxPlaySamples:
debugmsg(1014);
return def + 512;
case AHIDB_MaxRecordSamples:
debugmsg(1015);
return 0;
case AHIDB_MinMonitorVolume:
debugmsg(1016);
return 0x0;
case AHIDB_MaxMonitorVolume:
debugmsg(1017);
return 0x10000;
case AHIDB_MinInputGain:
debugmsg(1018);
return 0x0;
case AHIDB_MaxInputGain:
debugmsg(1019);
return 0x0;
case AHIDB_MinOutputVolume:
debugmsg(1020);
return 0x0;
case AHIDB_MaxOutputVolume:
debugmsg(1021);
return 0x10000;
case AHIDB_Inputs:
debugmsg(1022);
return 0;
case AHIDB_Input:
debugmsg(1023);
return 0;
case AHIDB_Outputs:
debugmsg(1024);
return 1;
case AHIDB_Output:
debugmsg(1025);
switch (arg) {
case 0: return (int32_t) "Snake 1";
case 1: return (int32_t) "Snake 2";
case 2: return (int32_t) "Snake 3";
case 3: return (int32_t) "Snake 4";
case 4: return (int32_t) "Snake 5";
case 5: return (int32_t) "Snake 6";
case 6: return (int32_t) "Snake 7";
case 7: return (int32_t) "Snake 8";
}
default:
debugmsg(1099);
return def;
}
}
static int32_t __attribute__((used)) intAHIsub_HardwareControl(uint32_t attr asm("d0"), uint32_t arg asm("d1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
return 0;
debugmsg(11);
int32_t rc = TRUE;
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
switch (attr) {
case AHIC_MonitorVolume:
debugmsg(1101);
ahi_data->monitor_volume = arg;
break;
case AHIC_MonitorVolume_Query:
debugmsg(1102);
rc = ahi_data->monitor_volume;
break;
case AHIC_InputGain:
debugmsg(1103);
ahi_data->input_gain = arg;
break;
case AHIC_InputGain_Query:
debugmsg(1104);
rc = ahi_data->input_gain;
break;
case AHIC_OutputVolume:
debugmsg(1105);
ahi_data->output_volume = arg;
break;
case AHIC_OutputVolume_Query:
debugmsg(1106);
rc = ahi_data->output_volume;
break;
case AHIC_Input:
debugmsg(1107);
break;
case AHIC_Input_Query:
debugmsg(1108);
break;
case AHIC_Output:
debugmsg(1109);
rc = TRUE;
break;
case AHIC_Output_Query:
debugmsg(1110);
rc = 0;
break;
default:
debugmsg(1199);
rc = FALSE;
break;
}
return rc;
}
static uint32_t __attribute__((used)) intAHIsub_SetEffect(uint8_t *effect asm("a0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
return AHIS_UNKNOWN;
}
static uint32_t __attribute__((used)) intAHIsub_LoadSound(uint16_t sound asm("d0"), uint32_t type asm("d1"), struct AHISampleInfo *info asm("a0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
return AHIS_UNKNOWN;
}
static uint32_t __attribute__((used)) intAHIsub_UnloadSound(uint16_t sound asm("d0"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
return AHIS_UNKNOWN;
}
static uint32_t __attribute__((used)) intAHIsub_Enable(struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
debugmsg(0x8000);
struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
//if (ahi_data->disable_cnt > 0)
//ahi_data->disable_cnt--;
//if (!ahi_data->disable_cnt) {
//debugmsg(141);
//Enable();
//}
Signal((struct Task *)ahi_data->slave_process, 1L << ahi_data->enable_signal);
return AHIE_OK;
}
static uint32_t __attribute__((used)) intAHIsub_Disable(struct AHIAudioCtrlDrv *AudioCtrl asm("a2"))
{
debugmsg(0x9000);
//struct pi_ahi *ahi_data = (struct pi_ahi*)AudioCtrl->ahiac_DriverData;
//if (!ahi_data->disable_cnt) {
//debugmsg(151);
//Disable();
//}
//ahi_data->disable_cnt++;
return AHIE_OK;
}
static uint32_t __attribute__((used)) intAHIsub_Update(uint32_t flags asm("d0"), struct AHIAudioCtrlDrv *AudioCtrlDrv asm("a2"))
{
debugmsg(16);
return AHIE_OK;
}
static uint32_t __attribute__((used)) intAHIsub_SetVol(uint16_t channel asm("d0"), uint32_t volume asm("d1"), uint32_t pan asm("d2"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"), uint32_t flags asm("d3"))
{
return AHIS_UNKNOWN;
}
static uint32_t __attribute__((used)) intAHIsub_SetFreq(uint16_t channel asm("d0"), uint32_t freq asm("d1"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"), uint32_t flags asm("d2"))
{
return AHIS_UNKNOWN;
}
static uint32_t __attribute__((used)) intAHIsub_SetSound(uint16_t channel asm("d0"), uint16_t sound asm("d1"), uint32_t offset asm("d2"), int32_t length asm("d3"), struct AHIAudioCtrlDrv *AudioCtrl asm("a2"), uint32_t flags asm("d4"))
{
return AHIS_UNKNOWN;
}
static uint32_t function_table[] = {
(uint32_t)open,
(uint32_t)close,
(uint32_t)expunge,
(uint32_t)null,
(uint32_t)intAHIsub_AllocAudio, // AllocAudio
(uint32_t)intAHIsub_FreeAudio, // FreeAudio
(uint32_t)intAHIsub_Disable, // Disable
(uint32_t)intAHIsub_Enable, // Enable
(uint32_t)intAHIsub_Start, // Start
(uint32_t)intAHIsub_Update, // Update
(uint32_t)intAHIsub_Stop, // Stop
(uint32_t)intAHIsub_SetVol, // SetVol
(uint32_t)intAHIsub_SetFreq, // SetFreq
(uint32_t)intAHIsub_SetSound, // SetSound
(uint32_t)intAHIsub_SetEffect, // SetEffect
(uint32_t)intAHIsub_LoadSound, // LoadSound
(uint32_t)intAHIsub_UnloadSound, // UnloadSound
(uint32_t)intAHIsub_GetAttr, // GetAttr
(uint32_t)intAHIsub_HardwareControl, // HardwareControl
(uint32_t)null,
(uint32_t)null,
(uint32_t)null,
-1
};
const uint32_t auto_init_tables[4] = {
sizeof(struct pi_ahi),
(uint32_t)function_table,
0,
(uint32_t)init,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment