mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-25 15:10:28 +00:00
Compare commits
28 commits
4363dcf82f
...
79d95ee140
Author | SHA1 | Date | |
---|---|---|---|
|
79d95ee140 | ||
|
a95d5559de | ||
|
5bd76304ec | ||
|
fca070fecf | ||
|
16004d084b | ||
|
f9bb43799b | ||
|
c370588653 | ||
|
f8729688b9 | ||
|
d58bc8c410 | ||
|
e599c67ca5 | ||
|
64703e9a12 | ||
|
0f1a63f0a2 | ||
|
74b770870f | ||
|
5696c3d0f1 | ||
|
8106bf6c02 | ||
|
6063c02243 | ||
|
b3af1628a2 | ||
|
926fd92849 | ||
|
f2490f75bc | ||
|
2fd8527fdb | ||
|
8200205781 | ||
|
55d95ee3d3 | ||
|
027edae296 | ||
|
ac7598808d | ||
|
bff3a763ea | ||
|
dcdde184ea | ||
|
276ab81094 | ||
|
b7821cbc95 |
25 changed files with 3591 additions and 41 deletions
|
@ -1,5 +1,5 @@
|
|||
/* AMD PCNetII Driver
|
||||
Author: TomAwezome
|
||||
Authors: ($TX,"minexew",HTML="https://github.com/minexew/"$), $TX,"TomAwezome",HTML="https://github.com/TomAwezome/"$, $TX,"TheTinkerer",HTML="https://github.com/tinkeros/"$
|
||||
|
||||
Driver is based on:
|
||||
- minexew's ShrineOS PCNet implementation
|
||||
|
@ -13,12 +13,6 @@
|
|||
- Clear documentation.
|
||||
*/
|
||||
|
||||
#define PCNET_CMDf_IOEN 0
|
||||
#define PCNET_CMDf_BMEN 2
|
||||
|
||||
#define PCNET_CMDF_IOEN (1 << PCNET_CMDf_IOEN)
|
||||
#define PCNET_CMDF_BMEN (1 << PCNET_CMDf_BMEN)
|
||||
|
||||
#define PCNET_WD_RESET 0x14 // reset reg location when card is in 16-bit mode
|
||||
|
||||
#define PCNET_DW_RDP 0x10
|
||||
|
@ -742,7 +736,7 @@ U0 PCNetInit()
|
|||
pcnet.pci->dev,
|
||||
pcnet.pci->fun,
|
||||
PCIR_COMMAND,
|
||||
PCNET_CMDF_IOEN | PCNET_CMDF_BMEN);
|
||||
PCI_CMDF_IOEN | PCI_CMDF_BMEN);
|
||||
|
||||
PCNetReset;
|
||||
|
||||
|
|
240
src/Home/Sound/AC97/AC97.ZC
Normal file
240
src/Home/Sound/AC97/AC97.ZC
Normal file
|
@ -0,0 +1,240 @@
|
|||
|
||||
#define INT_LAST_VALID_ENTRY 1 << 2
|
||||
#define INT_IOC 1 << 3
|
||||
#define INT_FIFO_ERR 1 << 4
|
||||
|
||||
#define BDL_BUF_SIZE 2044
|
||||
#define MAX_BDLS 32
|
||||
|
||||
#define PCM_BUF_SIZE 2048
|
||||
#define PCM_IN 0
|
||||
#define PCM_OUT 1
|
||||
#define MIC_IN 2
|
||||
|
||||
// Native Audio Mixer registers (all U16)
|
||||
#define RESET 0x00 // Reset Register
|
||||
#define MASTER_VOL 0x02 // Set Master Output Volume
|
||||
#define MIC_VOL 0x0E // Set Microphone Volume
|
||||
#define PCM_VOL 0x18 // Set Output Volume of PCM patterns
|
||||
#define REC_SLC 0x1A // Select Input Device
|
||||
#define REC_GAIN 0x1C // Set Input Gain
|
||||
#define MIC_GAIN 0x1E // Set Gain of Microphone
|
||||
#define EXT_ID 0x28 // Supported extended functions
|
||||
#define EXT_CTRL 0x2A // Enabling extended functions
|
||||
#define EXT_FRONT_RATE 0x2C // Sample rate of front speaker
|
||||
|
||||
// Native Audio Bus Master registers
|
||||
#define PCM_INPUT_REG_BOX 0x00 // NABM register box for PCM IN (sizeof NABM register box)
|
||||
#define PCM_OUTPUT_REG_BOX 0x10 // NABM register box for PCM OUT (sizeof NABM register box)
|
||||
#define MIC_INPUT_REG_BOX 0x20 // NABM register box for Microphone (sizeof NABM register box)
|
||||
#define GLOBAL_CTL 0x2C // Global Control Register (U32)
|
||||
#define GLOBAL_STS 0x30 // Global Status Register (U32)
|
||||
|
||||
// NABM register box registers
|
||||
#define BUFFER_DSC_ADDR 0x00 // Physical Address of Buffer Descriptor List (U32)
|
||||
#define CUR_ENTRY_VAL 0x04 // Number of Actual Processed Buffer Descriptor Entry (U8)
|
||||
#define LAST_VALID_ENTRY 0x05 // Number of all Descriptor Entries (U8)
|
||||
#define TRANSFER_STS 0x06 // Status of Transferring Data (U16)
|
||||
#define CUR_IDX_PROC_SAMPLES 0x08 // Number of Transferred Samples in Actual Processed Entry (U16)
|
||||
#define PRCSD_ENTRY 0x0A // Number of Actual Processed Buffer Entry (U8)
|
||||
#define BUFFER_CNT 0x0B // Most Important Register for controlling Transfers (U8)
|
||||
|
||||
class CAC97BufferDescriptorListEntry
|
||||
{
|
||||
U32 addr;
|
||||
U16 length; // length - 1
|
||||
U16 flags;
|
||||
};
|
||||
|
||||
class CAC97BufferDescriptorList
|
||||
{
|
||||
CAC97BufferDescriptorListEntry entries[32];
|
||||
};
|
||||
|
||||
class CAC97
|
||||
{
|
||||
CPCIInfo pci;
|
||||
CAC97BufferDescriptorList *bdl[3];
|
||||
U16 nam;
|
||||
U16 nabm;
|
||||
};
|
||||
|
||||
CAC97 ac97;
|
||||
|
||||
#define AUDIO_MAX_STREAMS 16
|
||||
#define AUDIO_OUTPUT_BUFFER_SIZE 1024
|
||||
#define AUDIO_STREAM_FIFO_SIZE 1048576 * 16
|
||||
#define AUDIO_STREAM_TYPE_INPUT 0
|
||||
#define AUDIO_STREAM_TYPE_OUTPUT 1
|
||||
|
||||
class CAudioStream
|
||||
{
|
||||
CFifoI64 *data;
|
||||
};
|
||||
|
||||
class CAudio
|
||||
{
|
||||
CAudioStream output[AUDIO_MAX_STREAMS];
|
||||
I64 output_frames[AUDIO_MAX_STREAMS];
|
||||
};
|
||||
|
||||
CAudio audio;
|
||||
|
||||
U0 AudioInit()
|
||||
{
|
||||
I64 i = 0;
|
||||
for (i = 0; i < AUDIO_MAX_STREAMS; i++)
|
||||
audio.output[i].data = FifoI64New(AUDIO_STREAM_FIFO_SIZE, sys_task);
|
||||
}
|
||||
|
||||
AudioInit;
|
||||
|
||||
I64 AudioAvailableOutputStreamGet()
|
||||
{
|
||||
I64 stream = 0;
|
||||
while (FifoI64Count(audio.output[stream].data))
|
||||
stream++;
|
||||
if (stream > AUDIO_MAX_STREAMS - 1)
|
||||
return -1;
|
||||
return stream;
|
||||
}
|
||||
|
||||
I64 AudioSFXPlay(U32 *data, I64 length)
|
||||
{
|
||||
I64 i;
|
||||
I64 stream = AudioAvailableOutputStreamGet;
|
||||
if (stream < 0)
|
||||
return stream;
|
||||
for (i = 0; i < length; i++)
|
||||
FifoI64Ins(audio.output[stream].data, data[i]);
|
||||
return stream;
|
||||
}
|
||||
|
||||
U0 AC97OutputMix(U32 *buf, I64 length = NULL)
|
||||
{
|
||||
I64 i;
|
||||
I64 j;
|
||||
I64 acc_sample_L = 0;
|
||||
I64 acc_sample_R = 0;
|
||||
I64 acc_streams = 0;
|
||||
U32 sample;
|
||||
|
||||
if (!length)
|
||||
length = AUDIO_OUTPUT_BUFFER_SIZE;
|
||||
for (i = 0; i < length / 4; i++)
|
||||
{
|
||||
acc_sample_L = 0;
|
||||
acc_sample_R = 0;
|
||||
acc_streams = 0;
|
||||
|
||||
for (j = 0; j < AUDIO_MAX_STREAMS; j++)
|
||||
{
|
||||
if (FifoI64Count(audio.output[j].data))
|
||||
{
|
||||
FifoI64Remove(audio.output[j].data, &sample);
|
||||
audio.output_frames[j]++;
|
||||
acc_streams++;
|
||||
acc_sample_L += sample.u16[0];
|
||||
acc_sample_R += sample.u16[1];
|
||||
}
|
||||
}
|
||||
|
||||
buf[i].i16[0] = ToI64(acc_sample_L / Sqrt(acc_streams));
|
||||
buf[i].i16[1] = ToI64(acc_sample_R / Sqrt(acc_streams));
|
||||
}
|
||||
}
|
||||
|
||||
U0 AC97BufferFill()
|
||||
{
|
||||
I64 idx = InU8(ac97.nabm + PCM_OUTPUT_REG_BOX + LAST_VALID_ENTRY);
|
||||
U32 *buf = ac97.bdl[PCM_OUT]->entries[idx].addr;
|
||||
AC97OutputMix(buf, BDL_BUF_SIZE);
|
||||
OutU8(ac97.nabm + PCM_OUTPUT_REG_BOX + LAST_VALID_ENTRY, ++idx);
|
||||
}
|
||||
|
||||
U0 AC97AudioProcess()
|
||||
{
|
||||
U16 status = InU16(ac97.nabm + PCM_OUTPUT_REG_BOX + TRANSFER_STS);
|
||||
if (status & INT_IOC)
|
||||
{
|
||||
AC97BufferFill;
|
||||
OutU16(ac97.nabm + PCM_OUTPUT_REG_BOX + TRANSFER_STS, 0x1C);
|
||||
}
|
||||
}
|
||||
|
||||
I64 AC97Init()
|
||||
{
|
||||
I64 i;
|
||||
I64 j;
|
||||
// Scan for device
|
||||
j = PCIClassFind(0x040100, 0);
|
||||
if (j < 0)
|
||||
{
|
||||
device_not_found: SysLog("\n[AC'97] Device not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PCIInfoGet(j, &ac97.pci);
|
||||
|
||||
if (ac97.pci.vendor_id != 0x8086 || ac97.pci.device_id != 0x2415)
|
||||
goto device_not_found;
|
||||
|
||||
ac97.nam = ac97.pci.bar[0] &0xFFFFFF00;
|
||||
ac97.nabm = ac97.pci.bar[1] &0xFFFFFF00;
|
||||
|
||||
// Enable port IO, disable MMIO
|
||||
PCIWriteU8(j.u8[2], j.u8[1], j.u8[0], 0x4, 5);
|
||||
|
||||
OutU32(ac97.nabm + GLOBAL_CTL, 0x03);
|
||||
OutU16(ac97.nam + RESET, 0xFFFF);
|
||||
|
||||
// Set PCM Output to Max volume
|
||||
OutU16(ac97.nam + PCM_VOL, 0x0000);
|
||||
|
||||
// Allocate Buffer Descriptor Lists
|
||||
ac97.bdl[PCM_IN] = CAllocAligned(sizeof(CAC97BufferDescriptorList), 4096, Fs->code_heap);
|
||||
ac97.bdl[PCM_OUT] = CAllocAligned(sizeof(CAC97BufferDescriptorList), 4096, Fs->code_heap);
|
||||
ac97.bdl[MIC_IN] = CAllocAligned(sizeof(CAC97BufferDescriptorList), 4096, Fs->code_heap);
|
||||
|
||||
for (i = 0; i < MAX_BDLS; i++)
|
||||
{
|
||||
ac97.bdl[PCM_OUT]->entries[i].addr =
|
||||
CAllocAligned(PCM_BUF_SIZE, 4096, Fs->code_heap);
|
||||
ac97.bdl[PCM_OUT]->entries[i].length = BDL_BUF_SIZE / 2;
|
||||
ac97.bdl[PCM_OUT]->entries[i].flags = 1 << 15;
|
||||
}
|
||||
|
||||
// Set addresses of Buffer Descriptor Lists
|
||||
// OutU32(ac97.nabm + PCM_INPUT_REG_BOX + BUFFER_DSC_ADDR, ac97.bdl[PCM_IN]);
|
||||
OutU32(ac97.nabm + PCM_OUTPUT_REG_BOX + BUFFER_DSC_ADDR, ac97.bdl[PCM_OUT]);
|
||||
// OutU32(ac97.nabm + MIC_INPUT_REG_BOX + BUFFER_DSC_ADDR, ac97.bdl[MIC_IN]);
|
||||
|
||||
// Set Master Volume
|
||||
OutU16(ac97.nam + MASTER_VOL, 0x0F0F);
|
||||
|
||||
// Stop playing sound
|
||||
OutU8(ac97.nabm + PCM_OUTPUT_REG_BOX + BUFFER_CNT, 0);
|
||||
|
||||
// Fill one buffers
|
||||
AC97BufferFill;
|
||||
|
||||
// Enable interrupt handler
|
||||
//@pci_register_int_handler(&@ac97_int_handler);
|
||||
|
||||
// Start playing sound
|
||||
OutU8(ac97.nabm + PCM_OUTPUT_REG_BOX + BUFFER_CNT, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 AC97Task()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
AC97AudioProcess;
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
AC97Init;
|
||||
Spawn(&AC97Task,, "AC97 Task", 1);
|
98
src/Home/Sound/AC97/Pci.ZC
Normal file
98
src/Home/Sound/AC97/Pci.ZC
Normal file
|
@ -0,0 +1,98 @@
|
|||
|
||||
#define PCI_INTH_MAX 16
|
||||
|
||||
U64 pci_int_handlers[PCI_INTH_MAX];
|
||||
|
||||
class CPCIInfo
|
||||
{
|
||||
U16 vendor_id;
|
||||
U16 device_id;
|
||||
U16 command;
|
||||
U16 status;
|
||||
U32 _class;
|
||||
U32 bar[6];
|
||||
U32 cap_pointer;
|
||||
};
|
||||
|
||||
class CPCICapability
|
||||
{
|
||||
U8 cap_vndr; /*Generic PCI field: PCI_CAP_ID_VNDR */
|
||||
U8 cap_next; /*Generic PCI field: next ptr. */
|
||||
U8 cap_len; /*Generic PCI field: capability length */
|
||||
U8 cfg_type; /*Identifies the structure. */
|
||||
U8 bar; /*Where to find it. */
|
||||
U8 padding[3]; /*Pad to full dword. */
|
||||
U32 offset; /*Offset within bar. */
|
||||
U32 length; /*Length of the structure, in bytes. */
|
||||
};
|
||||
|
||||
U0 PCIInfoGet(I64 i, CPCIInfo *pci)
|
||||
{
|
||||
I64 j;
|
||||
pci->vendor_id = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x0) &0xFFFF;
|
||||
pci->device_id = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x0) >> 16;
|
||||
pci->command = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x4) &0xFFFF;
|
||||
pci->status = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x4) >> 16;
|
||||
pci->_class = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x8) >> 24;
|
||||
for (j = 0; j < 6; j++)
|
||||
pci->bar[j] = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x10 + (0x04 * j));
|
||||
}
|
||||
|
||||
U0 PCIGetCapability(I64 i, CPCICapability *cap, I64 idx)
|
||||
{
|
||||
I64 base = 0x40 + (idx * 16);
|
||||
U32 u32;
|
||||
u32 = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base);
|
||||
cap->cap_vndr = u32.u8[0];
|
||||
cap->cap_next = u32.u8[1];
|
||||
cap->cap_len = u32.u8[2];
|
||||
cap->cfg_type = u32.u8[3];
|
||||
u32 = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x04);
|
||||
cap->bar = u32.u8[0];
|
||||
cap->offset = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x08);
|
||||
cap->length = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x0c);
|
||||
}
|
||||
|
||||
U0 PCIInterruptReroute(I64 base, I64 cpu)
|
||||
{
|
||||
I64 i;
|
||||
U8 *da = dev.uncached_alias + IOAPIC_REG;
|
||||
U32 *_d = dev.uncached_alias + IOAPIC_DATA;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
*da = IOREDTAB + i * 2 + 1;
|
||||
*_d = dev.mp_apic_ids[cpu] << 24;
|
||||
*da = IOREDTAB + i * 2;
|
||||
*_d = 0x4000 + base + i;
|
||||
}
|
||||
}
|
||||
|
||||
I64 PCIInterruptHandlerRegister(U64 handler)
|
||||
{
|
||||
if (!handler)
|
||||
return -1;
|
||||
I64 i = 0;
|
||||
while (pci_int_handlers[i])
|
||||
i++;
|
||||
if (i > PCI_INTH_MAX - 1)
|
||||
return -1;
|
||||
pci_int_handlers[i] = handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
interrupt U0 PCIInterruptHandler()
|
||||
{
|
||||
I64 i;
|
||||
for (i = 0; i < PCI_INTH_MAX; i++)
|
||||
if (pci_int_handlers[i])
|
||||
Call(pci_int_handlers[i]);
|
||||
*(dev.uncached_alias + LAPIC_EOI)(U32 *) = 0;
|
||||
}
|
||||
|
||||
MemSet(&pci_int_handlers, NULL, sizeof(U64) * PCI_INTH_MAX);
|
||||
// IntEntrySet(0x40, &PCIInterruptHandler, IDTET_IRQ);
|
||||
// IntEntrySet(0x41, &PCIInterruptHandler, IDTET_IRQ);
|
||||
// IntEntrySet(0x42, &PCIInterruptHandler, IDTET_IRQ);
|
||||
// IntEntrySet(0x43, &PCIInterruptHandler, IDTET_IRQ);
|
||||
//PCIInterruptReroute(0x40, 0);
|
102
src/Home/Sound/API.DD
Normal file
102
src/Home/Sound/API.DD
Normal file
|
@ -0,0 +1,102 @@
|
|||
|
||||
|
||||
AC97 Functions:
|
||||
|
||||
AudioInit
|
||||
AudioAvailableOutputStreamGet
|
||||
AudioSFXPlay
|
||||
AC97OutputMix
|
||||
AC97BufferFill
|
||||
AC97AudioProcess
|
||||
AC97Init
|
||||
AC97Task
|
||||
|
||||
AC97 Pci.ZC Functions:
|
||||
|
||||
PCIInfoGet
|
||||
PCIGetCapability
|
||||
PCIInterruptReroute
|
||||
PCIInterruptHandlerRegister
|
||||
PCIInterruptHandler
|
||||
|
||||
|
||||
================================================
|
||||
|
||||
HDAudio MakeSnd Functions:
|
||||
|
||||
SoundTaskEndCB
|
||||
|
||||
HDAudio SndMath Functions:
|
||||
|
||||
Saw
|
||||
FullSaw
|
||||
Caw
|
||||
FullCaw
|
||||
Tri
|
||||
FullTri
|
||||
Note2Ona
|
||||
Ona2Note
|
||||
Ona2Octave
|
||||
SinPhaseCont
|
||||
SndWaveCtrlNew
|
||||
SndWaveCtrlDel
|
||||
SndWaveAddBuf
|
||||
|
||||
HDAudio SndMusic Functions:
|
||||
|
||||
tM
|
||||
Beat
|
||||
MusicSetOctave
|
||||
MusicSetMeter
|
||||
MusicSetNoteLen
|
||||
Play
|
||||
MusicSettingsReset
|
||||
CurSongTask
|
||||
|
||||
|
||||
HDAudio SndEffects Functions:
|
||||
|
||||
SoundEffectEndTaskCB
|
||||
SoundEffectTask
|
||||
Noise
|
||||
Sweep
|
||||
|
||||
|
||||
HDAudio SndFile Functions:
|
||||
|
||||
SndFileCreate
|
||||
|
||||
HDAudio Functions:
|
||||
|
||||
HDSyncCORB
|
||||
HDWriteCORB
|
||||
HDSyncRIRB
|
||||
HDReadRIRB
|
||||
HDWriteCORBSync
|
||||
HDTestCORBSync
|
||||
HDTraverse
|
||||
HDRun
|
||||
HDStop
|
||||
HDSnd
|
||||
HDFillBuf
|
||||
HDAudioTaskEndCB
|
||||
HDTonesInit
|
||||
HDAudioTask
|
||||
HDRst
|
||||
HDAudioEnd
|
||||
HDAudioUncachedInit
|
||||
HDAudioInit
|
||||
HDAudioScan
|
||||
|
||||
HDAudio Cfg Functions:
|
||||
|
||||
HDCfgConnectList
|
||||
HDCfgTraverse
|
||||
HDCfgRandomizeXYZ
|
||||
HDCfgPopUpInfoTask
|
||||
HDCfgPopUpInfo
|
||||
HDCfgEdLink
|
||||
HDCfgSave
|
||||
HDCfg
|
||||
|
||||
================================================
|
5
src/Home/Sound/HDAudio1/Load.ZC
Normal file
5
src/Home/Sound/HDAudio1/Load.ZC
Normal file
|
@ -0,0 +1,5 @@
|
|||
Cd(__DIR__);
|
||||
|
||||
SysFile("Sup1CodeScraps/Mem/Mem2Meg.ZC");
|
||||
SysFile("Sup1Snd/MakeSnd.ZC");
|
||||
SysFile("Sup1HDAudio/HDAudio.ZC");
|
199
src/Home/Sound/HDAudio1/Sup1CodeScraps/Mem/Mem2Meg.ZC
Normal file
199
src/Home/Sound/HDAudio1/Sup1CodeScraps/Mem/Mem2Meg.ZC
Normal file
|
@ -0,0 +1,199 @@
|
|||
//Now, we use 1 Gig page table entries.
|
||||
|
||||
//See $LK,"./UncachedAlloc.ZC"$
|
||||
|
||||
U8 *Mem2MegAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
|
||||
{/*Alloc 2Meg pages from BlkPool. Don't link to task.
|
||||
(Linking to a task means they will be freed when the task dies.)
|
||||
It might give you more than you asked for
|
||||
so a ptr to a page count is passed.
|
||||
|
||||
Return: NULL if out of memory.
|
||||
*/
|
||||
I64 i,j,*pte,num=*_pages2Meg;
|
||||
CMemBlk *res=NULL,*m,*m1;
|
||||
|
||||
if (!bp) bp=sys_code_bp;
|
||||
PUSHFD
|
||||
CLI
|
||||
while (LBts(&bp->locked_flags,BPlf_LOCKED))
|
||||
PAUSE
|
||||
num<<=21-MEM_PAG_BITS;
|
||||
|
||||
m=&bp->mem_free_2meg_list;
|
||||
while (TRUE) {
|
||||
if (!(res=m->next))
|
||||
break;
|
||||
if (res->pags<num)
|
||||
m=res;
|
||||
else {
|
||||
if (res->pags==num) {
|
||||
m->next=res->next;
|
||||
goto am_done;
|
||||
} else {
|
||||
res->pags-=num;
|
||||
res(U8 *)+=res->pags<<MEM_PAG_BITS;
|
||||
res->pags=num;
|
||||
goto am_done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m=&bp->mem_free_list;
|
||||
while (TRUE) {
|
||||
if (!(res=m->next)) {
|
||||
num=0;
|
||||
res=NULL; //Out of memory
|
||||
goto am_done;
|
||||
}
|
||||
if (res->pags<num)
|
||||
m=res;
|
||||
else {
|
||||
if (res->pags==num) {
|
||||
if (res(U8 *)&0x1FFFFF)
|
||||
m=res;
|
||||
else {
|
||||
m->next=res->next;
|
||||
goto am_done;
|
||||
}
|
||||
} else {
|
||||
if (i=(res(U8 *)&0x1FFFFF)>>MEM_PAG_BITS) {
|
||||
j=1<<(21-MEM_PAG_BITS)-i;
|
||||
if (res->pags<num+j)
|
||||
m=res;
|
||||
else if (res->pags==num+j) {
|
||||
res->pags-=num;
|
||||
res(U8 *)+=res->pags<<MEM_PAG_BITS;
|
||||
res->pags=num;
|
||||
goto am_done;
|
||||
} else {
|
||||
m1=res;
|
||||
res(U8 *)+=j<<MEM_PAG_BITS;
|
||||
res->pags=num;
|
||||
m=res(U8 *)+num<<MEM_PAG_BITS;
|
||||
m->pags=m1->pags-num-j;
|
||||
m1->pags=j;
|
||||
m->next=m1->next;
|
||||
m1->next=m;
|
||||
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
|
||||
goto am_done;
|
||||
}
|
||||
} else {
|
||||
m=m->next=res(U8 *)+num<<MEM_PAG_BITS;
|
||||
m->next=res->next;
|
||||
m->pags=res->pags-num;
|
||||
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
|
||||
res->pags=num;
|
||||
goto am_done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
am_done:
|
||||
i=num<<MEM_PAG_BITS;
|
||||
bp->used_u8s+=i;
|
||||
num>>=21-MEM_PAG_BITS;
|
||||
*_pages2Meg=num;
|
||||
m=res;
|
||||
m1=m(U8 *)+i;
|
||||
while (m<m1) {
|
||||
pte=MemPageTable(m);
|
||||
*pte &= ~0x18;
|
||||
InvalidatePage(m);
|
||||
m(U8 *)+=0x200000;
|
||||
}
|
||||
LBtr(&bp->locked_flags,BPlf_LOCKED);
|
||||
POPFD
|
||||
return res;
|
||||
}
|
||||
|
||||
U8 *Mem2MegUncachedAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
|
||||
{/*Alloc 2Meg pages from BlkPool. Don't link to task.
|
||||
(Linking to a task means they will be freed when the task dies.)
|
||||
It will be marked uncached. It might give you more than you asked for
|
||||
so a ptr to a page count is passed.
|
||||
|
||||
Return: NULL if out of memory.
|
||||
*/
|
||||
CMemBlk *res,*m,*m1;
|
||||
I64 num=*_pages2Meg,*pte;
|
||||
if (res=Mem2MegAlloc(_pages2Meg,bp)) {
|
||||
num=*_pages2Meg;
|
||||
m=res;
|
||||
m1=m(U8 *)+num<<21;
|
||||
while (m<m1) {
|
||||
pte=MemPageTable(m);
|
||||
*pte= *pte& ~0x18 |0x10;
|
||||
InvalidatePage(m);
|
||||
m(U8 *)+=0x200000;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
U8 *Mem2MegWriteThruAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
|
||||
{/*Alloc 2Meg pages from BlkPool. Don't link to task.
|
||||
(Linking to a task means they will be freed when the task dies.)
|
||||
It will be marked write-through. It might give you more than you asked for
|
||||
so a ptr to a page count is passed.
|
||||
|
||||
Return: NULL if out of memory.
|
||||
*/
|
||||
CMemBlk *res,*m,*m1;
|
||||
I64 num=*_pages2Meg,*pte;
|
||||
if (res=Mem2MegAlloc(_pages2Meg,bp)) {
|
||||
num=*_pages2Meg;
|
||||
m=res;
|
||||
m1=m(U8 *)+num<<21;
|
||||
while (m<m1) {
|
||||
pte=MemPageTable(m);
|
||||
*pte= *pte& ~0x18 |8;
|
||||
InvalidatePage(m);
|
||||
m(U8 *)+=0x200000;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
U0 Mem2MegFree(CMemBlk *m,I64 pages2Meg,CBlkPool *bp=NULL)
|
||||
{//Return non-task 2Meg pages to BlkPool.
|
||||
I64 *pte;
|
||||
CMemBlk *m1,*m2;
|
||||
if (m) {
|
||||
if (!bp) bp=sys_code_bp;
|
||||
m2=m;
|
||||
m1=m(U8 *)+pages2Meg<<21;
|
||||
while (m2<m1) {
|
||||
pte=MemPageTable(m2);
|
||||
*pte=*pte & ~0x18;
|
||||
InvalidatePage(m2);
|
||||
m2(U8 *)+=0x200000;
|
||||
}
|
||||
PUSHFD
|
||||
CLI
|
||||
while (LBts(&bp->locked_flags,BPlf_LOCKED))
|
||||
PAUSE
|
||||
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
|
||||
m->pags=pages2Meg<<(21-MEM_PAG_BITS);
|
||||
bp->used_u8s-=pages2Meg<<21;
|
||||
m->next=bp->mem_free_2meg_list;
|
||||
bp->mem_free_2meg_list=m;
|
||||
LBtr(&bp->locked_flags,BPlf_LOCKED);
|
||||
POPFD
|
||||
}
|
||||
}
|
||||
|
||||
CHeapCtrl *HeapCtrlBPInit(CBlkPool *bp,I64 pags)
|
||||
{//Make mem chunk into HeapCtrl and BlkPool.
|
||||
I64 num;
|
||||
CMemBlk *m;
|
||||
CHeapCtrl *hc;
|
||||
MemSet(bp,0,sizeof(CBlkPool)+sizeof(CHeapCtrl));
|
||||
hc=HeapCtrlInit(bp(U8 *)+sizeof(CBlkPool),,bp);
|
||||
m=(bp(U8 *)+sizeof(CBlkPool)+sizeof(CHeapCtrl)+MEM_PAG_SIZE-1)&
|
||||
~(MEM_PAG_SIZE-1);
|
||||
num=(bp(U8 *)+pags<<MEM_PAG_BITS-m(U8 *))>>MEM_PAG_BITS;
|
||||
bp->alloced_u8s=(pags-num)<<MEM_PAG_BITS;
|
||||
BlkPoolAdd(bp,m,num);
|
||||
return hc;
|
||||
}
|
69
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/BeatFreq.ZC
Normal file
69
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/BeatFreq.ZC
Normal file
|
@ -0,0 +1,69 @@
|
|||
Bool beat_done;
|
||||
I64 start_buf_num;
|
||||
U0 (*fp_task_end_cb)();
|
||||
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||
|
||||
F64 freq1,freq2;
|
||||
|
||||
U0 BeatFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||
{ //Gets called by HD Audio task -- HDAudioTask().
|
||||
I64 j,m;
|
||||
F64 t;
|
||||
if (beat_done) return;
|
||||
t=ToF64((buf_num-start_buf_num)*(SND_BUF_LEN/SND_OCHANNELS))/SND_SAMPLE_RATE;
|
||||
j=0;
|
||||
while (j<SND_BUF_LEN) {
|
||||
m=I32_MAX*(Sin(freq1*(2*ã)*t)+Sin(freq2*(2*ã)*t));
|
||||
|
||||
//Samples are 24-bit, placed in upper 24 bits of an I32.
|
||||
m*=snd_vol;
|
||||
buf[j++]=ToI64(m)&0xFFFFFF00; //Left
|
||||
buf[j++]=ToI64(m)&0xFFFFFF00; //Right
|
||||
|
||||
t+=1.0/SND_SAMPLE_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
U0 BeatTaskEndCB()
|
||||
{
|
||||
beat_done=TRUE;
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
if (fp_task_end_cb)
|
||||
(*fp_task_end_cb)();
|
||||
else
|
||||
Exit;
|
||||
}
|
||||
|
||||
U0 BeatFreq()
|
||||
{
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
freq1=600.0;
|
||||
freq2=601.0;
|
||||
beat_done=FALSE;
|
||||
fp_task_end_cb=Fs->task_end_cb;
|
||||
Fs->task_end_cb=&BeatTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||
start_buf_num=snd_obuf_num;
|
||||
fp_old_fill_buf=fp_snd_fill_buf;
|
||||
fp_snd_fill_buf=&BeatFillBuf;
|
||||
try {
|
||||
"Pick two frequencies within a few Hz of each other to hear beats.\n"
|
||||
"Pick two frequencies a multiple of two for an octave harmonic.\n"
|
||||
"$$FG,GREEN$$<CTRL-ALT-C>$$FG$$ to exit.\n";
|
||||
while (TRUE) {
|
||||
freq1=440.0;//PmtF64("Freq #1 (%0.2fHz):",freq1,20,20000);
|
||||
freq2=880.0;//PmtF64("Freq #2 (%0.2fHz):",freq2,20,20000);
|
||||
Sleep(200);
|
||||
}
|
||||
} catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
}
|
||||
beat_done=TRUE;
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
}
|
||||
|
||||
BeatFreq;
|
16
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Chords.ZC
Normal file
16
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Chords.ZC
Normal file
|
@ -0,0 +1,16 @@
|
|||
U0 Chords(Bool val=ON)
|
||||
{
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
HDTonesInit;
|
||||
if (val) {
|
||||
hda.tone_swcs[1]->freq_multiplier=4.0/3.0;
|
||||
hda.tone_swcs[1]->amp_multiplier=1.0;
|
||||
hda.tone_swcs[2]->freq_multiplier=(4.0/3.0)`2;
|
||||
hda.tone_swcs[2]->amp_multiplier=1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Chords(ON);
|
98
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Echo.ZC
Normal file
98
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Echo.ZC
Normal file
|
@ -0,0 +1,98 @@
|
|||
Bool echo_done;
|
||||
|
||||
U0 (*fp_task_end_cb)();
|
||||
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||
U0 (*fp_old_copy_buf)(SND_IN_CONTAINER *buf,I64 buf_num)=NULL;
|
||||
|
||||
#define BUF_NUM 8
|
||||
SND_IN_CONTAINER my_buf[SND_BUF_LEN*BUF_NUM];
|
||||
|
||||
I64 my_ibuf_ptr,my_obuf_ptr;
|
||||
|
||||
U0 EchoFillBuf(SND_OUT_CONTAINER *buf,I64)
|
||||
{
|
||||
I64 j;
|
||||
if (echo_done) return;
|
||||
j=0;
|
||||
while (j<SND_BUF_LEN) {
|
||||
buf[j++]=ToI64(snd_vol*my_buf[my_obuf_ptr++
|
||||
&(SND_BUF_LEN*BUF_NUM-1)])<<16&0xFFFFFF00;
|
||||
buf[j++]=ToI64(snd_vol*my_buf[my_obuf_ptr++
|
||||
&(SND_BUF_LEN*BUF_NUM-1)])<<16&0xFFFFFF00;
|
||||
}
|
||||
}
|
||||
|
||||
U0 EchoCopyBuf(SND_IN_CONTAINER *buf,I64)
|
||||
{
|
||||
I64 j;
|
||||
if (echo_done) return;
|
||||
j=0;
|
||||
while (j<SND_BUF_LEN) {
|
||||
my_buf[my_ibuf_ptr++ &(SND_BUF_LEN*BUF_NUM-1)]=buf[j++];
|
||||
my_buf[my_ibuf_ptr++ &(SND_BUF_LEN*BUF_NUM-1)]=buf[j++];
|
||||
}
|
||||
}
|
||||
|
||||
U0 EchoTaskEndCB()
|
||||
{
|
||||
echo_done=TRUE;
|
||||
HDStop(TRUE,FALSE);
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
fp_snd_copy_buf=fp_old_copy_buf;
|
||||
if (fp_task_end_cb)
|
||||
(*fp_task_end_cb)();
|
||||
else
|
||||
Exit;
|
||||
}
|
||||
|
||||
U0 DrawIt(CTask *task,CDC *dc)
|
||||
{
|
||||
SND_IN_CONTAINER *buf=hda.istr0_buf[0];
|
||||
I64 i,x1,y1,x2=0,y2=0,
|
||||
cy=task->pix_height>>1;
|
||||
dc->color=BLUE;
|
||||
for (i=0;i<SND_BUF_LEN;i++) {
|
||||
x1=i*task->pix_width/SND_BUF_LEN;
|
||||
y1=cy-buf[i]*cy/I16_MAX;
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
x2=x1;
|
||||
y2=y1;
|
||||
}
|
||||
}
|
||||
|
||||
U0 EchoDemo()
|
||||
{
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
HDRun(TRUE,TRUE);
|
||||
echo_done=FALSE;
|
||||
fp_task_end_cb=Fs->task_end_cb;
|
||||
Fs->task_end_cb=&EchoTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||
my_ibuf_ptr=(BUF_NUM/2)*SND_BUF_LEN;
|
||||
my_obuf_ptr=0;
|
||||
fp_old_fill_buf=fp_snd_fill_buf;
|
||||
fp_old_copy_buf=fp_snd_copy_buf;
|
||||
fp_snd_fill_buf=&EchoFillBuf;
|
||||
fp_snd_copy_buf=&EchoCopyBuf;
|
||||
DocCursor;
|
||||
DocClear;
|
||||
Fs->draw_it=&DrawIt;
|
||||
try
|
||||
CharGet;
|
||||
catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
fp_snd_copy_buf=fp_old_copy_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
}
|
||||
echo_done=TRUE;
|
||||
HDStop(TRUE,FALSE);
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
fp_snd_copy_buf=fp_old_copy_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
SettingsPop;
|
||||
}
|
||||
|
||||
EchoDemo;
|
17
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Guitar.ZC
Normal file
17
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Guitar.ZC
Normal file
|
@ -0,0 +1,17 @@
|
|||
U0 Guitar(Bool val=ON,F64 à=0.7)
|
||||
{
|
||||
I64 i;
|
||||
F64 m;
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
HDTonesInit;
|
||||
if (val)
|
||||
for (i=0,m=1.0;i<HD_TONES;i++,m*=à) {
|
||||
hda.tone_swcs[i]->freq_multiplier=i+1;
|
||||
hda.tone_swcs[i]->amp_multiplier=m;
|
||||
}
|
||||
}
|
||||
|
||||
Guitar(ON);
|
96
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/PolyPhonic.ZC
Normal file
96
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/PolyPhonic.ZC
Normal file
|
@ -0,0 +1,96 @@
|
|||
Bool poly_done;
|
||||
I64 start_buf_num;
|
||||
U0 (*fp_task_end_cb)();
|
||||
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||
|
||||
U0 PolyFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||
{ //Gets called by HD Audio task -- HDAudioTask().
|
||||
|
||||
//Note: the buffer is in uncached memory
|
||||
//so you might want to avoid multiple
|
||||
//accesses due to slow speed. (If you were
|
||||
//to add a bunch of waveforms together, you
|
||||
//might want to do it in a cached buffer
|
||||
//and copy it once.)
|
||||
|
||||
I64 j,m,r;
|
||||
F64 t,d;
|
||||
if (poly_done) return;
|
||||
t=ToF64((buf_num-start_buf_num)*(SND_BUF_LEN/SND_OCHANNELS))/SND_SAMPLE_RATE;
|
||||
j=0;
|
||||
while (j<SND_BUF_LEN) {
|
||||
d=0.5*Sin(1.0*(2*ã)*t)+0.5; //Stereo pos from 0.0-1.0
|
||||
r=RandI32;
|
||||
m=0;
|
||||
|
||||
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(220.0*(2*ã)*t);
|
||||
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(222.0*(2*ã)*t);
|
||||
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(880.0*(2*ã)*t);
|
||||
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(884.0*(2*ã)*t);
|
||||
m+=0.4*r*Caw(t,.125);
|
||||
if (Caw(t-.25,0.5)<=0.05)
|
||||
m+=0.3*r*Caw(t,0.05);
|
||||
if (t>4.0) {
|
||||
if (0.90<Caw(t,1.0))
|
||||
m+=0.6*I32_MAX*Caw(t,0.1)*FullCaw(t,0.001);
|
||||
if (t>8.0) {
|
||||
if (0.70<Caw(t,1.0)<0.90)
|
||||
m+=0.4*I32_MAX*Caw(t-.7,0.5)*FullCaw(t,0.00075);
|
||||
if (t>12.0) {
|
||||
if (0.30<Caw(t,1.0)<0.40)
|
||||
m+=0.4*I32_MAX*Sin(100.0/(1.1-Saw(t,0.01)));
|
||||
if (t>16.0)
|
||||
m+=0.3*I32_MAX*Caw(t,1.0/6)*Sin(440.0*(2*ã)*t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Samples are 24-bit, placed in upper 24 bits of an I32.
|
||||
m*=snd_vol;
|
||||
buf[j++]=ToI64(m*d)&0xFFFFFF00; //Left
|
||||
buf[j++]=ToI64(m*(1.0-d))&0xFFFFFF00; //Right
|
||||
|
||||
t+=1.0/SND_SAMPLE_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
U0 PolyTaskEndCB()
|
||||
{
|
||||
poly_done=TRUE;
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
if (fp_task_end_cb)
|
||||
(*fp_task_end_cb)();
|
||||
else
|
||||
Exit;
|
||||
}
|
||||
|
||||
U0 PolyPhonic()
|
||||
{
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
poly_done=FALSE;
|
||||
fp_task_end_cb=Fs->task_end_cb;
|
||||
Fs->task_end_cb=&PolyTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||
start_buf_num=snd_obuf_num;
|
||||
fp_old_fill_buf=fp_snd_fill_buf;
|
||||
fp_snd_fill_buf=&PolyFillBuf;
|
||||
try
|
||||
#if __CMD_LINE__
|
||||
PressAKey;
|
||||
#else
|
||||
View;
|
||||
#endif
|
||||
catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
}
|
||||
poly_done=TRUE;
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
}
|
||||
|
||||
#if __CMD_LINE__
|
||||
PolyPhonic;
|
||||
#endif
|
117
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Record.ZC
Normal file
117
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Record.ZC
Normal file
|
@ -0,0 +1,117 @@
|
|||
Bool record_stop,record_done;
|
||||
|
||||
U0 (*fp_old_copy_buf)(SND_IN_CONTAINER *buf,I64 buf_num)=NULL;
|
||||
|
||||
#define RECORD_BUF_SIZE (SND_BUF_LEN*0x100)
|
||||
|
||||
SND_IN_CONTAINER *record_buf[2];
|
||||
I64 record_buf_iptr,record_ibuf_num,record_obuf_num;
|
||||
|
||||
U0 RecordCopyBuf(SND_IN_CONTAINER *buf,I64)
|
||||
{
|
||||
I64 j;
|
||||
SND_IN_CONTAINER *_s=record_buf[record_ibuf_num&1];
|
||||
j=0;
|
||||
while (j<SND_BUF_LEN) {
|
||||
_s[record_buf_iptr++]=buf[j++];
|
||||
j++; //Record in mono
|
||||
}
|
||||
if (record_buf_iptr>=RECORD_BUF_SIZE) {
|
||||
record_buf_iptr=0;
|
||||
record_ibuf_num++;
|
||||
}
|
||||
}
|
||||
|
||||
U0 DrawIt(CTask *task,CDC *dc)
|
||||
{
|
||||
SND_IN_CONTAINER *buf=hda.istr0_buf[0];
|
||||
I64 i,x1,y1,x2=0,y2=0,
|
||||
cy=task->pix_height>>1;
|
||||
dc->color=BLUE;
|
||||
for (i=0;i<SND_BUF_LEN;i++) {
|
||||
x1=i*task->pix_width/SND_BUF_LEN;
|
||||
y1=cy-buf[i]*cy/I16_MAX;
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
x2=x1;
|
||||
y2=y1;
|
||||
}
|
||||
dc->color=RED;
|
||||
}
|
||||
|
||||
U0 RecordTaskEndCB()
|
||||
{
|
||||
fp_snd_copy_buf=fp_old_copy_buf;
|
||||
HDStop(TRUE,FALSE);
|
||||
Free(record_buf[0]);
|
||||
Free(record_buf[1]);
|
||||
record_done=TRUE;
|
||||
Exit;
|
||||
}
|
||||
|
||||
U0 RecordTask(U8 *filename)
|
||||
{
|
||||
Bool old_io_snd;
|
||||
U8 *filename=StrNew(filename),*filename2;
|
||||
TaskInitExt; //needed for disk access
|
||||
record_buf[0]=CAlloc(RECORD_BUF_SIZE*sizeof(SND_IN_CONTAINER));
|
||||
record_buf[1]=CAlloc(RECORD_BUF_SIZE*sizeof(SND_IN_CONTAINER));
|
||||
FileExtRemove(filename);
|
||||
record_buf_iptr=0;
|
||||
record_ibuf_num=0;
|
||||
record_obuf_num=0;
|
||||
record_done=FALSE;
|
||||
Fs->task_end_cb=&RecordTaskEndCB;
|
||||
fp_old_copy_buf=fp_snd_copy_buf;
|
||||
fp_snd_copy_buf=&RecordCopyBuf;
|
||||
HDRun(TRUE,FALSE);
|
||||
old_io_snd=IOSnd(OFF);
|
||||
while (!record_stop) {
|
||||
if (record_ibuf_num>record_obuf_num) {
|
||||
filename2=MPrint("%s%04d.SNZ",filename,record_obuf_num);
|
||||
SndFileWrite(filename2,record_buf[record_obuf_num&1],RECORD_BUF_SIZE);
|
||||
record_obuf_num++;
|
||||
Free(filename2);
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
filename2=MPrint("%s%04d.SNZ",filename,record_obuf_num);
|
||||
SndFileWrite(filename2,record_buf[record_obuf_num&1],record_buf_iptr);
|
||||
record_obuf_num++;
|
||||
Free(filename2);
|
||||
Free(filename);
|
||||
IOSnd(old_io_snd);
|
||||
record_done=TRUE;
|
||||
}
|
||||
|
||||
U0 RecordDemo(U8 *filename="~/Record.SNZ")
|
||||
{
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
record_done=FALSE;
|
||||
record_stop=FALSE;
|
||||
Spawn(&RecordTask,filename,"Record .SNZ",,Fs);
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
DocCursor;
|
||||
DocClear;
|
||||
Fs->draw_it=&DrawIt;
|
||||
try
|
||||
CharGet;
|
||||
catch //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||
record_stop=TRUE;
|
||||
record_stop=TRUE;
|
||||
while (record_done)
|
||||
Yield;
|
||||
SettingsPop;
|
||||
while (TRUE) {
|
||||
"\n\nPlay ";
|
||||
if (YorN)
|
||||
SndFilePlaySeq(filename,record_obuf_num);
|
||||
else
|
||||
break;
|
||||
}
|
||||
NewLine(2);
|
||||
}
|
||||
|
||||
RecordDemo;
|
44
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/SndScope.ZC
Normal file
44
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/SndScope.ZC
Normal file
|
@ -0,0 +1,44 @@
|
|||
U0 DrawIt(CTask *task,CDC *dc)
|
||||
{
|
||||
SND_OUT_CONTAINER *buf=hda.ostr0_buf[0];
|
||||
I64 i,x1,y1,x2,y2,
|
||||
cy=task->pix_height>>1;
|
||||
|
||||
dc->color=BLUE;
|
||||
x2=0;y2=cy;
|
||||
for (i=0;i<SND_BUF_LEN;i+=2) {
|
||||
x1=i*task->pix_width/SND_BUF_LEN;
|
||||
y1=cy-buf[i]*cy/snd_vol/I32_MAX;
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
x2=x1;y2=y1;
|
||||
}
|
||||
|
||||
dc->color=GREEN;
|
||||
x2=0;y2=cy;
|
||||
for (i=1;i<SND_BUF_LEN;i+=2) {
|
||||
x1=i*task->pix_width/SND_BUF_LEN;
|
||||
y1=cy-buf[i]*cy/snd_vol/I32_MAX;
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
x2=x1; y2=y1;
|
||||
}
|
||||
}
|
||||
|
||||
U0 SndScope()
|
||||
{
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
WinHorz(1,18);
|
||||
WinVert(15,TEXT_ROWS-2);
|
||||
DocCursor;
|
||||
DocClear;
|
||||
Fs->draw_it=&DrawIt;
|
||||
CharGet;
|
||||
SettingsPop;
|
||||
}
|
||||
|
||||
#if __CMD_LINE__
|
||||
SndScope;
|
||||
#endif
|
287
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Synth.ZC
Normal file
287
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Synth.ZC
Normal file
|
@ -0,0 +1,287 @@
|
|||
#define M_WAVEFORM 0
|
||||
#define M_FREQUENCY 1
|
||||
#define M_ENVELOPE 2
|
||||
|
||||
#define M_MODES_NUM 3
|
||||
|
||||
I64 mode;
|
||||
Bool my_ms_down;
|
||||
I64 last_x,last_y;
|
||||
|
||||
Bool synth_done;
|
||||
|
||||
U0 (*fp_task_end_cb)();
|
||||
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||
|
||||
#define BUF_NUM 8
|
||||
SND_OUT_CONTAINER my_buf[SND_BUF_LEN*BUF_NUM];
|
||||
|
||||
#define WF_BUF_LEN 2048
|
||||
#define WF_Y_SCALE 2048.0
|
||||
I64 waveform_buf[WF_BUF_LEN];
|
||||
|
||||
#define FQ_BUF_LEN 2048
|
||||
#define FQ_Y_SCALE 2048.0
|
||||
I64 frequency_buf[FQ_BUF_LEN];
|
||||
F64 fq_scale;
|
||||
|
||||
#define EL_BUF_LEN 2048
|
||||
#define EL_Y_SCALE 2048.0
|
||||
I64 envelope_buf[EL_BUF_LEN];
|
||||
F64 el_scale;
|
||||
|
||||
U0 SynthFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||
{
|
||||
I64 i,j,l,k0,k1,k2,k3;
|
||||
F64 d;
|
||||
static F64 k=0;
|
||||
if (synth_done) return;
|
||||
j=0;
|
||||
k0=buf_num*(SND_BUF_LEN/SND_OCHANNELS);
|
||||
while (j<SND_BUF_LEN) {
|
||||
k1=WF_BUF_LEN*k/(SND_BUF_LEN/SND_OCHANNELS);
|
||||
k2=fq_scale*FQ_BUF_LEN*k0/(SND_BUF_LEN/SND_OCHANNELS);
|
||||
k3=el_scale*EL_BUF_LEN*k0/(SND_BUF_LEN/SND_OCHANNELS);
|
||||
|
||||
d=envelope_buf[k3%EL_BUF_LEN]/EL_Y_SCALE;
|
||||
d*=snd_vol;
|
||||
d*=I32_MAX*waveform_buf[k1%WF_BUF_LEN]/WF_Y_SCALE;
|
||||
i=ToI64(d)&0xFFFFFF00;
|
||||
|
||||
for (l=0;l<SND_OCHANNELS;l++)
|
||||
buf[j++]=i;
|
||||
|
||||
d=frequency_buf[k2%FQ_BUF_LEN]/FQ_Y_SCALE; // [0.0,1.0]
|
||||
d=(SND_BUF_LEN/SND_OCHANNELS)*Exp(5.0*d+4)/SND_SAMPLE_RATE;
|
||||
k+=d;
|
||||
k0++;
|
||||
}
|
||||
}
|
||||
|
||||
U0 SynthTaskEndCB()
|
||||
{
|
||||
synth_done=TRUE;
|
||||
HDStop(TRUE,FALSE);
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
if (fp_task_end_cb)
|
||||
(*fp_task_end_cb)();
|
||||
else
|
||||
Exit;
|
||||
}
|
||||
|
||||
Bool WFPlot(U8 *,I64 x,I64 y,I64)
|
||||
{
|
||||
if (0<=x<=WF_BUF_LEN)
|
||||
waveform_buf[x]=y;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool FQPlot(U8 *,I64 x,I64 y,I64)
|
||||
{
|
||||
if (0<=x<=FQ_BUF_LEN)
|
||||
frequency_buf[x]=AbsI64(y);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool ELPlot(U8 *,I64 x,I64 y,I64)
|
||||
{
|
||||
if (0<=x<=EL_BUF_LEN)
|
||||
envelope_buf[x]=AbsI64(y);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
U0 DrawIt(CTask *task,CDC *dc)
|
||||
{
|
||||
I64 i,x1,y1,x2,y2,
|
||||
cy=task->pix_height>>1,
|
||||
h_max=task->pix_width-1;
|
||||
|
||||
if (!winmgr.show_menu) {
|
||||
if (mouse.lb) {
|
||||
if (my_ms_down)
|
||||
switch (mode) {
|
||||
case M_WAVEFORM:
|
||||
Line(NULL,
|
||||
(last_x-task->pix_left-task->scroll_x)*WF_BUF_LEN/h_max,
|
||||
WF_Y_SCALE*(cy-last_y+task->pix_top+task->scroll_y)/cy,0,
|
||||
// ( msx-task->pix_left-task->scroll_x)*WF_BUF_LEN/h_max,
|
||||
( mouse.pos.x-task->pix_left-task->scroll_x)*WF_BUF_LEN/h_max,
|
||||
// WF_Y_SCALE*(cy-msy+task->pix_top+task->scroll_y)/cy,0,
|
||||
WF_Y_SCALE*(cy-mouse.pos.y+task->pix_top+task->scroll_y)/cy,0,
|
||||
&WFPlot);
|
||||
break;
|
||||
case M_FREQUENCY:
|
||||
Line(NULL,
|
||||
(last_x-task->pix_left-task->scroll_x)*FQ_BUF_LEN/h_max,
|
||||
FQ_Y_SCALE*(cy-last_y+task->pix_top+task->scroll_y)/cy,0,
|
||||
// ( msx-task->pix_left-task->scroll_x)*FQ_BUF_LEN/h_max,
|
||||
( mouse.pos.x-task->pix_left-task->scroll_x)*FQ_BUF_LEN/h_max,
|
||||
// FQ_Y_SCALE*(cy-msy+task->pix_top+task->scroll_y)/cy,0,
|
||||
FQ_Y_SCALE*(cy-mouse.pos.y+task->pix_top+task->scroll_y)/cy,0,
|
||||
&FQPlot);
|
||||
break;
|
||||
case M_ENVELOPE:
|
||||
Line(NULL,
|
||||
(last_x-task->pix_left-task->scroll_x)*EL_BUF_LEN/h_max,
|
||||
EL_Y_SCALE*(cy-last_y+task->pix_top+task->scroll_y)/cy,0,
|
||||
// ( msx-task->pix_left-task->scroll_x)*EL_BUF_LEN/h_max,
|
||||
( mouse.pos.x-task->pix_left-task->scroll_x)*EL_BUF_LEN/h_max,
|
||||
// EL_Y_SCALE*(cy-msy+task->pix_top+task->scroll_y)/cy,0,
|
||||
EL_Y_SCALE*(cy-mouse.pos.y+task->pix_top+task->scroll_y)/cy,0,
|
||||
&ELPlot);
|
||||
break;
|
||||
}
|
||||
my_ms_down=TRUE;
|
||||
// last_x=msx;
|
||||
// last_y=msy;
|
||||
last_x=mouse.pos.x;
|
||||
last_y=mouse.pos.y;
|
||||
} else
|
||||
my_ms_down=FALSE;
|
||||
}
|
||||
|
||||
x2=-1;
|
||||
if (mode==M_WAVEFORM && Blink) {
|
||||
dc->color=ROPF_DITHER+WHITE<<16+RED;
|
||||
GrPrint(dc,0,cy-FONT_HEIGHT,"Set Waveform.");
|
||||
} else
|
||||
dc->color=RED;
|
||||
for (i=0;i<WF_BUF_LEN;i++) {
|
||||
x1=i*task->pix_width/WF_BUF_LEN;
|
||||
y1=cy-cy*waveform_buf[i]/WF_Y_SCALE;
|
||||
if (x2>=0)
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
x2=x1;
|
||||
y2=y1;
|
||||
}
|
||||
|
||||
x2=-1;
|
||||
if (mode==M_FREQUENCY && Blink) {
|
||||
dc->color=ROPF_DITHER+WHITE<<16+BLUE;
|
||||
GrPrint(dc,0,cy-FONT_HEIGHT,"Set Frequency.");
|
||||
} else
|
||||
dc->color=BLUE;
|
||||
for (i=0;i<FQ_BUF_LEN;i++) {
|
||||
x1=i*task->pix_width/FQ_BUF_LEN;
|
||||
y1=cy-cy*frequency_buf[i]/FQ_Y_SCALE;
|
||||
if (x2>=0)
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
GrLine(dc,x2,cy-(y2-cy),x1,cy-(y1-cy));
|
||||
x2=x1;
|
||||
y2=y1;
|
||||
}
|
||||
|
||||
x2=-1;
|
||||
if (mode==M_ENVELOPE && Blink) {
|
||||
dc->color=ROPF_DITHER+WHITE<<16+GREEN;
|
||||
GrPrint(dc,0,cy-FONT_HEIGHT,"Set Envelope.");
|
||||
} else
|
||||
dc->color=GREEN;
|
||||
for (i=0;i<EL_BUF_LEN;i++) {
|
||||
x1=i*task->pix_width/EL_BUF_LEN;
|
||||
y1=cy-cy*envelope_buf[i]/EL_Y_SCALE;
|
||||
if (x2>=0)
|
||||
GrLine(dc,x2,y2,x1,y1);
|
||||
GrLine(dc,x2,cy-(y2-cy),x1,cy-(y1-cy));
|
||||
x2=x1;
|
||||
y2=y1;
|
||||
}
|
||||
|
||||
dc->color=BLACK;
|
||||
GrLine(dc,0,cy,task->pix_width,cy);
|
||||
}
|
||||
|
||||
U0 SetMenu()
|
||||
{
|
||||
MenuEntryFind(Fs->cur_menu,"Mode/Waveform")->checked=mode==M_WAVEFORM;
|
||||
MenuEntryFind(Fs->cur_menu,"Mode/Frequency")->checked=mode==M_FREQUENCY;
|
||||
MenuEntryFind(Fs->cur_menu,"Mode/Envelope")->checked=mode==M_ENVELOPE;
|
||||
}
|
||||
|
||||
U0 Init()
|
||||
{
|
||||
my_ms_down=FALSE;
|
||||
mode=M_WAVEFORM;
|
||||
MemSetI64(&waveform_buf[0] ,-0.5 *WF_Y_SCALE,WF_BUF_LEN/2);
|
||||
MemSetI64(&waveform_buf[WF_BUF_LEN/2] , 0.5 *WF_Y_SCALE,WF_BUF_LEN/2);
|
||||
MemSetI64(frequency_buf , 0.25*FQ_Y_SCALE,FQ_BUF_LEN);
|
||||
MemSetI64(envelope_buf , 0.75*EL_Y_SCALE,EL_BUF_LEN);
|
||||
fq_scale=0.02;
|
||||
el_scale=0.02;
|
||||
SetMenu;
|
||||
}
|
||||
|
||||
U0 Synth()
|
||||
{
|
||||
I64 arg1,arg2;
|
||||
if (snd_dev!=SD_HD_AUDIO) {
|
||||
"Only works for HD Audio.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
MenuPush(
|
||||
"File {"
|
||||
" New(,'\n');"
|
||||
" Abort(,CH_SHIFT_ESC);"
|
||||
" Exit(,CH_ESC);"
|
||||
"}"
|
||||
"Mode {"
|
||||
" Waveform(,'1');"
|
||||
" Frequency(,'2');"
|
||||
" Envelope(,'3');"
|
||||
"}"
|
||||
);
|
||||
AutoComplete;
|
||||
WinBorder;
|
||||
WinMax;
|
||||
DocCursor;
|
||||
DocClear;
|
||||
Fs->win_inhibit=WIG_TASK_DEFAULT-WIF_SELF_FOCUS-WIF_FOCUS_TASK_MENU;
|
||||
|
||||
Init;
|
||||
|
||||
synth_done=FALSE;
|
||||
fp_task_end_cb=Fs->task_end_cb;
|
||||
Fs->task_end_cb=&SynthTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||
fp_old_fill_buf=fp_snd_fill_buf;
|
||||
fp_snd_fill_buf=&SynthFillBuf;
|
||||
Fs->draw_it=&DrawIt;
|
||||
try {
|
||||
while (TRUE) {
|
||||
switch (MessageGet(&arg1,&arg2,1<<MESSAGE_KEY_DOWN+1<<MESSAGE_MS_R_DOWN)) {
|
||||
case MESSAGE_KEY_DOWN:
|
||||
switch (arg1) {
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
mode=arg1-'1';
|
||||
SetMenu;
|
||||
break;
|
||||
case '\n':
|
||||
Init;
|
||||
break;
|
||||
case CH_SHIFT_ESC:
|
||||
case CH_ESC:
|
||||
goto sy_done;
|
||||
}
|
||||
break;
|
||||
case MESSAGE_MS_R_DOWN:
|
||||
if (++mode==M_MODES_NUM)
|
||||
mode=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sy_done:
|
||||
MessageGet(,,1<<MESSAGE_KEY_UP);
|
||||
} catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
}
|
||||
synth_done=TRUE;
|
||||
fp_snd_fill_buf=fp_old_fill_buf;
|
||||
Fs->task_end_cb=fp_task_end_cb;
|
||||
SettingsPop;
|
||||
}
|
||||
|
||||
Synth;
|
722
src/Home/Sound/HDAudio1/Sup1HDAudio/HDAudio.ZC
Normal file
722
src/Home/Sound/HDAudio1/Sup1HDAudio/HDAudio.ZC
Normal file
|
@ -0,0 +1,722 @@
|
|||
//SysFile("~/sup1hdaudio/Sup1CodeScraps/Mem/Mem2Meg.ZC");
|
||||
|
||||
#help_index "Sound/HDAudio"
|
||||
|
||||
//snd devs
|
||||
#define SD_PC_SPEAKER 0
|
||||
#define SD_HD_AUDIO 1
|
||||
|
||||
#define SND_SAMPLE_RATE 48000
|
||||
#define SND_SAMPLE_BITS 24
|
||||
#define SND_OCHANNELS 2
|
||||
#define SND_ICHANNELS 2
|
||||
#define SND_OUT_CONTAINER I32
|
||||
#define SND_IN_CONTAINER I16
|
||||
#define SND_BUF_LEN 0x400
|
||||
#define SND_BUF_TIME_mS (SND_BUF_LEN / SND_OCHANNELS * 1000.0 / SND_SAMPLE_RATE)
|
||||
|
||||
F64 snd_freq = 0;
|
||||
I64 snd_dev = SD_PC_SPEAKER;
|
||||
Bool snd_record = FALSE;
|
||||
F64 snd_vol = 0.1;
|
||||
U0 (*fp_snd) (F64 freq, I64 waveform, F64 amp) = NULL;
|
||||
U0 (*fp_snd_record)(F64 freq, I64 waveform, F64 amp) = NULL;
|
||||
U0 (*fp_snd_fill_buf)(SND_OUT_CONTAINER *buf, I64 buf_num) = NULL;
|
||||
U0 (*fp_snd_copy_buf)(SND_IN_CONTAINER *buf, I64 buf_num) = NULL;
|
||||
|
||||
I64 snd_obuf_num, snd_ibuf_num;
|
||||
|
||||
#define Sf_FILLING_OUT 0
|
||||
I64 snd_flags;
|
||||
|
||||
#define HD_1_CHAN 0
|
||||
#define HD_2_CHAN 1
|
||||
#define HD_3_CHAN 2
|
||||
#define HD_4_CHAN 3
|
||||
|
||||
#define HD_8_BIT 0
|
||||
#define HD_16_BIT 1
|
||||
#define HD_20_BIT 2
|
||||
#define HD_24_BIT 3
|
||||
#define HD_32_BIT 4
|
||||
#define HD_48kHz 0
|
||||
|
||||
#define HD_DEFAULT_OUT_FMT (HD_2_CHAN + HD_24_BIT << 4 + HD_48kHz << 8)
|
||||
#define HD_DEFAULT_IN_FMT (HD_2_CHAN + HD_16_BIT << 4 + HD_48kHz << 8)
|
||||
|
||||
#define HD_POS_BUF_MULTIPLES 0x1000
|
||||
|
||||
#define HD_CORB_ENTRIES 256
|
||||
#define HD_RIRB_ENTRIES 256
|
||||
#define HD_BDL_ENTRIES 256
|
||||
|
||||
#define HD_GCTL 0x08
|
||||
#define HD_STATESTS 0x0E
|
||||
#define HD_GSTS 0x10
|
||||
#define HD_CORBLBASE 0x40
|
||||
#define HD_CORBUBASE 0x44
|
||||
#define HD_CORBWP 0x48
|
||||
#define HD_CORBRP 0x4A
|
||||
#define HD_CORBCTL 0x4C
|
||||
#define HD_CORBST 0x4D
|
||||
#define HD_RIRBLBASE 0x50
|
||||
#define HD_RIRBUBASE 0x54
|
||||
#define HD_RIRBWP 0x58
|
||||
#define HD_RIRBCTL 0x5C
|
||||
#define HD_RIRBSTS 0x5D
|
||||
|
||||
#define STRCTL 0x00
|
||||
#define STRSTS 0x03
|
||||
#define STRLPIB 0x04
|
||||
#define STRCBL 0x08
|
||||
#define STRLVI 0x0C
|
||||
#define STRFIFOW 0x0E
|
||||
#define STRFIFOS 0x10
|
||||
#define STRFMT 0x12
|
||||
#define STRBDPL 0x18
|
||||
#define STRBDPU 0x1C
|
||||
#define ISTR0 0x080
|
||||
#define ISTR1 0x0A0
|
||||
#define ISTR2 0x0C0
|
||||
#define ISTR3 0x0E0
|
||||
#define OSTR0 0x100
|
||||
#define OSTR1 0x120
|
||||
#define OSTR2 0x140
|
||||
#define OSTR3 0x160
|
||||
|
||||
#define VERB_GET_PARAM 0xF0000
|
||||
#define VERB_CONNECT_SEL_GET 0xF0100
|
||||
#define VERB_CONNECT_SEL_SET 0x70100
|
||||
#define VERB_GET_CONNECT_LST 0xF0200
|
||||
#define VERB_PROCESS_STATE_GET 0xF0300
|
||||
#define VERB_PROCESS_STATE_SET 0x70300
|
||||
#define VERB_COEFF_IDX_GET 0xD0000
|
||||
#define VERB_COEFF_IDX_SET 0x50000
|
||||
#define VERB_PROCESS_COEFF_GET 0xC0000
|
||||
#define VERB_PROCESS_COEFF_SET 0x40000
|
||||
#define VERB_AMPLIFIER_GAIN_GET 0xB0000
|
||||
#define VERB_AMPLIFIER_GAIN_SET 0x30000
|
||||
#define VERB_STREAM_FMT_GET 0xA0000
|
||||
#define VERB_STREAM_FMT_SET 0x20000
|
||||
#define VERB_DIGIT_CONVERT1_GET 0xF0D00
|
||||
#define VERB_DIGIT_CONVERT1_SET 0x70D00
|
||||
#define VERB_DIGIT_CONVERT2_GET 0xF0D00
|
||||
#define VERB_DIGIT_CONVERT2_SET 0x70E00
|
||||
#define VERB_POWER_STATE_GET 0xF0500
|
||||
#define VERB_POWER_STATE_SET 0x70500
|
||||
#define VERB_CHAN_STREAM_ID_GET 0xF0600
|
||||
#define VERB_CHAN_STREAM_ID_SET 0x70600
|
||||
#define VERB_SDI_SEL_GET 0xF0400
|
||||
#define VERB_SDI_SEL_SET 0x70400
|
||||
#define VERB_PIN_WIDGET_CTL_GET 0xF0700
|
||||
#define VERB_PIN_WIDGET_CTL_SET 0x70700
|
||||
#define VERB_UNSOL_ENABLE_GET 0xF0800
|
||||
#define VERB_UNSOL_ENABLE_SET 0x70800
|
||||
#define VERB_PIN_SENSE_GET 0xF0900
|
||||
#define VERB_PIN_SENSE_SET 0x70900
|
||||
#define VERB_EAPDBTL_ENABLE_GET 0xF0C00
|
||||
#define VERB_EAPDBTL_ENABLE_SET 0x70C00
|
||||
#define VERB_BEEP_CTL_GET 0xF0A00
|
||||
#define VERB_BEEP_CTL_SET 0x70A00
|
||||
#define VERB_GPI_CTRL0_GET 0xF1000
|
||||
#define VERB_GPI_CTRL0_SET 0x71000
|
||||
#define VERB_GPI_CTRL1_GET 0xF1100
|
||||
#define VERB_GPI_CTRL1_SET 0x71100
|
||||
#define VERB_GPI_CTRL2_GET 0xF1200
|
||||
#define VERB_GPI_CTRL2_SET 0x71200
|
||||
#define VERB_GPI_CTRL3_GET 0xF1300
|
||||
#define VERB_GPI_CTRL3_SET 0x71300
|
||||
#define VERB_GPI_CTRL4_GET 0xF1400
|
||||
#define VERB_GPI_CTRL4_SET 0x71400
|
||||
#define VERB_GPI_CTRL5_GET 0xF1500
|
||||
#define VERB_GPI_CTRL5_SET 0x71500
|
||||
#define VERB_GPI_CTRL6_GET 0xF1600
|
||||
#define VERB_GPI_CTRL6_SET 0x71600
|
||||
#define VERB_GPI_CTRL7_GET 0xF1700
|
||||
#define VERB_GPI_CTRL7_SET 0x71700
|
||||
#define VERB_GPI_CTRL8_GET 0xF1800
|
||||
#define VERB_GPI_CTRL8_SET 0x71800
|
||||
#define VERB_GPI_CTRL9_GET 0xF1900
|
||||
#define VERB_GPI_CTRL9_SET 0x71900
|
||||
#define VERB_GPI_CTRLA_GET 0xF1A00
|
||||
#define VERB_GPI_CTRLA_SET 0x71A00
|
||||
#define VERB_VOL_CTL_GET 0xF0F00
|
||||
#define VERB_VOL_CTL_SET 0x70F00
|
||||
#define VERB_SUB_SYS_ID0_GET 0xF2000
|
||||
#define VERB_SUB_SYS_ID0_SET 0x72000
|
||||
#define VERB_SUB_SYS_ID1_GET 0xF2000
|
||||
#define VERB_SUB_SYS_ID1_SET 0x72100
|
||||
#define VERB_SUB_SYS_ID2_GET 0xF2000
|
||||
#define VERB_SUB_SYS_ID2_SET 0x72200
|
||||
#define VERB_SUB_SYS_ID3_GET 0xF2000
|
||||
#define VERB_SUB_SYS_ID3_SET 0x72300
|
||||
#define VERB_CFG_DEFAULT0_GET 0xF1C00
|
||||
#define VERB_CFG_DEFAULT0_SET 0x71C00
|
||||
#define VERB_CFG_DEFAULT1_GET 0xF1C00
|
||||
#define VERB_CFG_DEFAULT1_SET 0x71D00
|
||||
#define VERB_CFG_DEFAULT2_GET 0xF1C00
|
||||
#define VERB_CFG_DEFAULT2_SET 0x71E00
|
||||
#define VERB_CFG_DEFAULT3_GET 0xF1C00
|
||||
#define VERB_CFG_DEFAULT3_SET 0x71F00
|
||||
#define VERB_STRIPE_CTL_GET 0xF2400
|
||||
#define VERB_STRIPE_CTL_SET 0x72400
|
||||
#define VERB_RST 0x7FF00
|
||||
|
||||
//Parameters
|
||||
#define P_VENDOR_ID 0x00
|
||||
#define P_REVISION_ID 0x02
|
||||
#define P_SUBNODE_CNT 0x04
|
||||
#define P_FUN_GRP_TYPE 0x05
|
||||
#define P_AUDIO_FUN_CAP 0x08
|
||||
#define P_AUDIO_WIDGET_CAP 0x09
|
||||
#define P_SAMPLE_SIZE_RATE_CAP 0x0A
|
||||
#define P_STREAM_FMTS 0x0B
|
||||
#define P_PIN_CAP 0x0C
|
||||
#define P_INPUT_AMP_CAP 0x0D
|
||||
#define P_OUTPUT_AMP_CAP 0x12
|
||||
#define P_CONNECT_LST_LEN 0x0E
|
||||
#define P_POWER_STATES 0x0F
|
||||
#define P_PROCESSING_CAP 0x10
|
||||
#define P_GPIO_CNT 0x11
|
||||
#define P_VOL_KNOB_CAP 0x13
|
||||
|
||||
//Function Group Types
|
||||
//00 reserved
|
||||
#define FGT_AUDIO 1
|
||||
#define FGT_VENDOR_MODEM 2
|
||||
//03-7F reserved
|
||||
//80-FF vendor function group
|
||||
|
||||
//Audio Widget Types
|
||||
#define AWT_OUTPUT 0x0
|
||||
#define AWT_INPUT 0x1
|
||||
#define AWT_MIXER 0x2
|
||||
#define AWT_SELECTOR 0x3
|
||||
#define AWT_PIN_COMPLEX 0x4
|
||||
#define AWT_POWER_WIDGET 0x5
|
||||
#define AWT_VOL_KNOB_WIDGET 0x6
|
||||
#define AWT_BEEP_GEN_WIDGET 0x7
|
||||
#define AWT_VENDOR 0xF
|
||||
#define AWT_NODE 0x10
|
||||
DefineListLoad("ST_AUDIO_WIDGET_TYPES",
|
||||
"Output\0"
|
||||
"Input\0"
|
||||
"Mixer\0"
|
||||
"Selector\0"
|
||||
"Pin Complex\0"
|
||||
"Power Widget\0"
|
||||
"Vol Knob\0"
|
||||
"Beep Gen\0"
|
||||
" \0"
|
||||
" \0"
|
||||
" \0"
|
||||
" \0"
|
||||
" \0"
|
||||
" \0"
|
||||
" \0"
|
||||
"Vendor\0"
|
||||
"Node\0");
|
||||
|
||||
class CHDBufDesc
|
||||
{
|
||||
I32 *buf;
|
||||
U32 len;
|
||||
U32 ctrl;
|
||||
};
|
||||
|
||||
#define HD_TONES 8
|
||||
|
||||
class CHDAudioCtrl
|
||||
{
|
||||
U8 *bar;
|
||||
CBlkPool *bp;
|
||||
CHeapCtrl *hc;
|
||||
I64 cad;
|
||||
U32 *corb;
|
||||
I64 *rirb;
|
||||
CHDBufDesc *ostr0_bdl,
|
||||
*istr0_bdl;
|
||||
SND_OUT_CONTAINER *ostr0_buf[2],
|
||||
*o_tmp_buf;
|
||||
SND_IN_CONTAINER *istr0_buf[2];
|
||||
CTask *task;
|
||||
I64 waveform;
|
||||
F64 freq, amp;
|
||||
CSndWaveCtrl *tone_swcs[HD_TONES];
|
||||
U8 rirb_rp, corb_wp;
|
||||
Bool audio_task_started, in_running, out_running;
|
||||
} hda;
|
||||
|
||||
MemSet(&hda, 0, sizeof(CHDAudioCtrl));
|
||||
|
||||
U0 HDAudioRegWriteU32(U16 hd_reg, U32 val)
|
||||
{
|
||||
U32 *dest = hda.bar + hd_reg;
|
||||
*dest = val;
|
||||
}
|
||||
|
||||
U0 HDAudioRegWriteU16(U16 hd_reg, U16 val)
|
||||
{
|
||||
U16 *dest = hda.bar + hd_reg;
|
||||
*dest = val;
|
||||
}
|
||||
|
||||
U0 HDAudioRegWriteU8(U16 hd_reg, U8 val)
|
||||
{
|
||||
U8 *dest = hda.bar + hd_reg;
|
||||
*dest = val;
|
||||
}
|
||||
|
||||
U32 HDAudioRegReadU32(U16 hd_reg)
|
||||
{
|
||||
U32 *dest = hda.bar + hd_reg;
|
||||
return *dest;
|
||||
}
|
||||
|
||||
U16 HDAudioRegReadU16(U16 hd_reg)
|
||||
{
|
||||
U16 *dest = hda.bar + hd_reg;
|
||||
return *dest;
|
||||
}
|
||||
|
||||
U8 HDAudioRegReadU8(U16 hd_reg)
|
||||
{
|
||||
U8 *dest = hda.bar + hd_reg;
|
||||
return *dest;
|
||||
}
|
||||
|
||||
U0 HDSyncCORB()
|
||||
{
|
||||
HDAudioRegWriteU16(HD_CORBWP, hda.corb_wp);
|
||||
while (HDAudioRegReadU16(HD_CORBRP) & 0xFF != hda.corb_wp)
|
||||
Yield;
|
||||
}
|
||||
|
||||
U0 HDWriteCORB(I64 cad, I64 nid, U32 val)
|
||||
{
|
||||
val |= cad << 28 + nid << 20;
|
||||
hda.corb[++hda.corb_wp] = val;
|
||||
}
|
||||
|
||||
I64 HDSyncRIRB()
|
||||
{
|
||||
I64 wp = HDAudioRegReadU16(HD_RIRBWP), res = 0;
|
||||
|
||||
while (hda.rirb_rp != wp)
|
||||
res = hda.rirb[++hda.rirb_rp];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 HDReadRIRB()
|
||||
{
|
||||
I64 wp, res = 0;
|
||||
|
||||
do
|
||||
{
|
||||
Yield;
|
||||
wp = HDAudioRegReadU16(HD_RIRBWP);
|
||||
} while (wp == hda.rirb_rp);
|
||||
res = hda.rirb[++hda.rirb_rp];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 HDWriteCORBSync(I64 cad, I64 nid, U32 val)
|
||||
{
|
||||
HDSyncCORB;
|
||||
HDSyncRIRB;
|
||||
HDWriteCORB(cad, nid, val);
|
||||
HDSyncCORB;
|
||||
return HDReadRIRB;
|
||||
}
|
||||
|
||||
Bool HDTestCORBSync(I64 cad, I64 nid, U32 val)
|
||||
{
|
||||
//Checks for a response
|
||||
I64 wp;
|
||||
|
||||
HDSyncCORB;
|
||||
HDSyncRIRB;
|
||||
HDWriteCORB(cad, nid, val);
|
||||
HDSyncCORB;
|
||||
|
||||
Sleep(1);
|
||||
wp = HDAudioRegReadU16(HD_RIRBWP);
|
||||
if (wp == hda.rirb_rp)
|
||||
return FALSE;
|
||||
HDReadRIRB;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
U0 HDTraverse(I64 cad, I64 nid)
|
||||
{
|
||||
I64 i, len, aud_cap, type;
|
||||
HDWriteCORBSync(cad, nid, VERB_POWER_STATE_SET + 0x00); //0 is on
|
||||
HDWriteCORBSync(cad, nid, VERB_EAPDBTL_ENABLE_SET + 0x02);
|
||||
HDWriteCORBSync(cad, nid, VERB_PROCESS_STATE_SET + 0x02);
|
||||
HDWriteCORBSync(cad, nid, VERB_CONNECT_SEL_SET + 0x00);
|
||||
aud_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_SUBNODE_CNT);
|
||||
if (aud_cap.u16[0])
|
||||
{
|
||||
for (i = aud_cap.u16[1]; i < aud_cap.u16[1] + aud_cap.u16[0]; i++)
|
||||
HDTraverse(cad, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
aud_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_AUDIO_WIDGET_CAP);
|
||||
type = aud_cap >> 20 & 15;
|
||||
if (Bt(&aud_cap, 8))
|
||||
len = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_CONNECT_LST_LEN) & 127;
|
||||
else
|
||||
len = 0;
|
||||
HDWriteCORBSync(cad, nid, VERB_AMPLIFIER_GAIN_SET + 0xF07F); //set I/O amp #0
|
||||
for (i = 1; i < len; i++)
|
||||
//Set IN amps to mute
|
||||
HDWriteCORBSync(cad, nid, VERB_AMPLIFIER_GAIN_SET + 0x7080 + i << 8);
|
||||
switch (type)
|
||||
{
|
||||
case AWT_OUTPUT:
|
||||
// if (FALSE) //if disabled // ????
|
||||
// HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||
// else
|
||||
HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x10);
|
||||
HDWriteCORBSync(cad, nid, VERB_STREAM_FMT_SET + HD_DEFAULT_OUT_FMT); // TODO: check format streams support ?
|
||||
HDWriteCORBSync(cad, nid, VERB_PROCESS_STATE_SET + 0x01);
|
||||
break;
|
||||
case AWT_INPUT:
|
||||
// if (TRUE) //if disabled // ????
|
||||
HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||
// else
|
||||
// HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x20);
|
||||
HDWriteCORBSync(cad, nid, VERB_STREAM_FMT_SET + HD_DEFAULT_IN_FMT); // TODO: check format streams support ?
|
||||
HDWriteCORBSync(cad, nid, VERB_PROCESS_STATE_SET + 0x01);
|
||||
break;
|
||||
case AWT_PIN_COMPLEX:
|
||||
HDWriteCORBSync(cad, nid, VERB_PIN_WIDGET_CTL_SET + 0xE2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDRun(Bool in, Bool out)
|
||||
{
|
||||
if (hda.bar)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
HDAudioRegWriteU32(OSTR0 + STRCTL, 0x100002); // ??
|
||||
hda.out_running = TRUE;
|
||||
}
|
||||
|
||||
if (in)
|
||||
{
|
||||
HDAudioRegWriteU32(ISTR0 + STRCTL, 0x200002); // ??
|
||||
hda.in_running = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDStop(Bool in, Bool out)
|
||||
{
|
||||
if (hda.bar)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
HDAudioRegWriteU32(OSTR0 + STRCTL, 0); // ??
|
||||
hda.out_running = FALSE;
|
||||
}
|
||||
|
||||
if (in)
|
||||
{
|
||||
HDAudioRegWriteU32(ISTR0 + STRCTL, 0); // ??
|
||||
hda.in_running = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDSnd(F64 freq, I64 waveform = WF_SQUARE, F64 amp = 1.0)
|
||||
{
|
||||
hda.waveform = waveform;
|
||||
hda.amp = amp;
|
||||
hda.freq = freq;
|
||||
}
|
||||
|
||||
U0 HDFillBuf(SND_OUT_CONTAINER *buf, I64)
|
||||
{
|
||||
I64 i, size = SND_BUF_LEN * sizeof(SND_OUT_CONTAINER);
|
||||
|
||||
if (!hda.o_tmp_buf)
|
||||
hda.o_tmp_buf = SysMAlloc(size);
|
||||
MemSet(hda.o_tmp_buf, 0, size);
|
||||
for (i = 0; i < HD_TONES; i++)
|
||||
SndWaveAddBuf(hda.tone_swcs[i], hda.o_tmp_buf, SND_BUF_LEN / SND_OCHANNELS, hda.freq, hda.waveform, snd_vol * hda.amp);
|
||||
MemCopy(buf, hda.o_tmp_buf, size);
|
||||
}
|
||||
|
||||
U0 HDAudioTaskEndCB()
|
||||
{
|
||||
I64 i;
|
||||
|
||||
HDStop(FALSE, TRUE);
|
||||
fp_snd = NULL;
|
||||
for (i = 0; i < HD_TONES; i++)
|
||||
{
|
||||
SndWaveCtrlDel(hda.tone_swcs[i]);
|
||||
hda.tone_swcs[i] = NULL;
|
||||
}
|
||||
|
||||
Exit;
|
||||
}
|
||||
|
||||
public U0 HDTonesInit()
|
||||
{
|
||||
I64 i;
|
||||
|
||||
if (hda.bar)
|
||||
{
|
||||
for (i = 0; i < HD_TONES; i++)
|
||||
{
|
||||
hda.tone_swcs[i]->freq_multiplier = 1.0;
|
||||
hda.tone_swcs[i]->amp_multiplier = 0;
|
||||
}
|
||||
|
||||
hda.tone_swcs[0]->amp_multiplier = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDAudioTask(I64)
|
||||
{
|
||||
//I didn't feel like messing around with PCI interrupts
|
||||
//so this task polls every millisecond to know when to
|
||||
//switch buffers.
|
||||
I64 i, next_obuf_trigger = SND_BUF_LEN * sizeof(SND_OUT_CONTAINER) / 2,
|
||||
obuf_rollover = 0,
|
||||
next_ibuf_trigger = SND_BUF_LEN * sizeof(SND_IN_CONTAINER),
|
||||
ibuf_rollover = 0;
|
||||
U32 *pos_in_obuf = hda.bar + OSTR0 + STRLPIB,
|
||||
*pos_in_ibuf = hda.bar + ISTR0 + STRLPIB;
|
||||
|
||||
Fs->task_end_cb = &HDAudioTaskEndCB;
|
||||
for (i = 0; i < HD_TONES; i++)
|
||||
hda.tone_swcs[i] = SndWaveCtrlNew;
|
||||
HDTonesInit;
|
||||
hda.freq = 0;
|
||||
Sound;
|
||||
fp_snd = &HDSnd;
|
||||
fp_snd_fill_buf = &HDFillBuf;
|
||||
fp_snd_copy_buf = NULL;
|
||||
snd_obuf_num = 1;
|
||||
snd_ibuf_num = 1;
|
||||
HDRun(FALSE, TRUE);
|
||||
hda.audio_task_started = TRUE; //This flag is probably not necessary
|
||||
while (TRUE)
|
||||
{
|
||||
if (next_obuf_trigger - obuf_rollover <=
|
||||
*pos_in_obuf <
|
||||
next_obuf_trigger - obuf_rollover + (HD_POS_BUF_MULTIPLES - 1) * SND_BUF_LEN * sizeof(SND_OUT_CONTAINER))
|
||||
{
|
||||
next_obuf_trigger += SND_BUF_LEN * sizeof(SND_OUT_CONTAINER);
|
||||
if (next_obuf_trigger - obuf_rollover >= HD_POS_BUF_MULTIPLES * SND_BUF_LEN * sizeof(SND_OUT_CONTAINER))
|
||||
obuf_rollover += HD_POS_BUF_MULTIPLES * SND_BUF_LEN * sizeof(SND_OUT_CONTAINER);
|
||||
if (fp_snd_fill_buf)
|
||||
{
|
||||
LBts(&snd_flags, Sf_FILLING_OUT);
|
||||
(*fp_snd_fill_buf)(hda.ostr0_buf[snd_obuf_num & 1], snd_obuf_num);
|
||||
if (IsMute)
|
||||
MemSet(hda.ostr0_buf[snd_obuf_num & 1], 0, SND_BUF_LEN * sizeof(SND_OUT_CONTAINER));
|
||||
LBtr(&snd_flags, Sf_FILLING_OUT);
|
||||
}
|
||||
|
||||
snd_obuf_num++;
|
||||
}
|
||||
|
||||
if (next_ibuf_trigger - ibuf_rollover <=
|
||||
*pos_in_ibuf <
|
||||
next_ibuf_trigger - ibuf_rollover + (HD_POS_BUF_MULTIPLES - 1) * SND_BUF_LEN * sizeof(SND_IN_CONTAINER))
|
||||
{
|
||||
next_ibuf_trigger += SND_BUF_LEN* sizeof(SND_IN_CONTAINER);
|
||||
if (next_ibuf_trigger - ibuf_rollover >= HD_POS_BUF_MULTIPLES * SND_BUF_LEN * sizeof(SND_IN_CONTAINER))
|
||||
ibuf_rollover += HD_POS_BUF_MULTIPLES * SND_BUF_LEN * sizeof(SND_IN_CONTAINER);
|
||||
if (fp_snd_copy_buf)
|
||||
(*fp_snd_copy_buf)(hda.istr0_buf[snd_obuf_num & 1], snd_ibuf_num);
|
||||
snd_ibuf_num++;
|
||||
}
|
||||
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDReset()
|
||||
{
|
||||
U32 d;
|
||||
|
||||
HDStop(TRUE, TRUE);
|
||||
HDAudioRegWriteU32(HD_GCTL, 0); //rst // ??
|
||||
do
|
||||
{
|
||||
Sleep(1);
|
||||
d = HDAudioRegReadU32(HD_GCTL);
|
||||
} while (d & 1);
|
||||
HDAudioRegWriteU32(HD_GCTL, 1); //??
|
||||
do
|
||||
{
|
||||
Sleep(1);
|
||||
d = HDAudioRegReadU32(HD_GCTL);
|
||||
} while (!(d & 1));
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
public U0 HDAudioEnd(Bool rst = TRUE)
|
||||
{
|
||||
snd_dev = SD_PC_SPEAKER;
|
||||
if (hda.bar)
|
||||
{
|
||||
Kill(hda.task);
|
||||
hda.task = NULL;
|
||||
if (rst)
|
||||
HDReset;
|
||||
FreeAll(hda.corb, hda.rirb, hda.o_tmp_buf, hda.ostr0_buf[0], hda.ostr0_buf[1], hda.istr0_buf[0], hda.istr0_buf[1],
|
||||
hda.ostr0_bdl, hda.istr0_bdl);
|
||||
Mem32DevFree(hda.bar);
|
||||
hda.bar = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDAudioUncachedInit()
|
||||
{
|
||||
I64 shared_blks = 1;
|
||||
hda.bp = Mem2MegUncachedAlloc(&shared_blks);
|
||||
hda.hc = HeapCtrlBPInit(hda.bp, shared_blks << 12);
|
||||
}
|
||||
|
||||
public Bool HDAudioInit(I64 hd_bus, I64 hd_dev, I64 hd_fun)
|
||||
{
|
||||
I64 i;
|
||||
U16 w, val;
|
||||
|
||||
if (hda.bar)
|
||||
HDAudioEnd;
|
||||
else
|
||||
HDAudioUncachedInit;
|
||||
if (PCIReadU16(hd_bus, hd_dev, hd_fun, PCIR_VENDOR_ID) == 0x8086 &&
|
||||
(hda.bar = dev.uncached_alias + PCIReadU32(hd_bus, hd_dev, hd_fun, PCIR_BASE0) & ~0x1F))
|
||||
{
|
||||
/* Set HDAudio PCI device command
|
||||
register IO Enable, Bus
|
||||
Master Enable, Memory Space,and
|
||||
Interrupt Disable bits. */
|
||||
val = PCIReadU16(hd_bus, hd_dev, hd_fun, PCIR_COMMAND);
|
||||
val |= PCI_CMDF_IOEN | PCI_CMDF_BMEN | PCI_CMDF_INTD | PCI_CMDF_MSEN;
|
||||
PCIWriteU16(hd_bus, hd_dev, hd_fun, PCIR_COMMAND, val);
|
||||
|
||||
HDReset;
|
||||
|
||||
hda.corb = CAllocAligned(HD_CORB_ENTRIES * sizeof(U32), 128, hda.hc);
|
||||
HDAudioRegWriteU32(HD_CORBLBASE, hda.corb(I64).u32[0]);
|
||||
HDAudioRegWriteU32(HD_CORBUBASE, hda.corb(I64).u32[1]);
|
||||
|
||||
hda.rirb = CAllocAligned(HD_RIRB_ENTRIES * sizeof(I64), 128, hda.hc);
|
||||
HDAudioRegWriteU32(HD_RIRBLBASE, hda.rirb(I64).u32[0]);
|
||||
HDAudioRegWriteU32(HD_RIRBUBASE, hda.rirb(I64).u32[1]);
|
||||
|
||||
HDAudioRegWriteU16(HD_CORBRP, 0x8000); //Rst read ptr // ??
|
||||
do
|
||||
{
|
||||
Yield;
|
||||
w = HDAudioRegReadU16(HD_CORBRP);
|
||||
} while (!(w & 0x8000));
|
||||
HDAudioRegWriteU16(HD_CORBRP, 0x0000); //Rst read ptr // ??
|
||||
do
|
||||
{
|
||||
Yield;
|
||||
w = HDAudioRegReadU16(HD_CORBRP);
|
||||
} while (w & 0x8000);
|
||||
|
||||
HDAudioRegWriteU16(HD_RIRBWP, 0x8000); //Rst write ptr // ??
|
||||
|
||||
HDAudioRegWriteU8(HD_CORBCTL, 0x02); //Run // ??
|
||||
HDAudioRegWriteU8(HD_RIRBCTL, 0x02); //Run // ??
|
||||
|
||||
hda.corb_wp = HDAudioRegReadU16(HD_CORBWP);
|
||||
hda.rirb_rp = HDAudioRegReadU16(HD_RIRBWP);
|
||||
|
||||
hda.ostr0_bdl = CAllocAligned(HD_BDL_ENTRIES * sizeof(CHDBufDesc), 128, hda.hc);
|
||||
HDAudioRegWriteU32(OSTR0 + STRBDPL, hda.ostr0_bdl(I64).u32[0]);
|
||||
HDAudioRegWriteU32(OSTR0 + STRBDPU, hda.ostr0_bdl(I64).u32[1]);
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
hda.ostr0_bdl[i].buf = hda.ostr0_buf[i] = CAllocAligned(SND_BUF_LEN * sizeof(SND_OUT_CONTAINER), 128, hda.hc);
|
||||
hda.ostr0_bdl[i].len = SND_BUF_LEN * sizeof(SND_OUT_CONTAINER);
|
||||
hda.ostr0_bdl[i].ctrl = 1;
|
||||
}
|
||||
|
||||
hda.istr0_bdl = CAllocAligned(HD_BDL_ENTRIES * sizeof(CHDBufDesc), 128, hda.hc);
|
||||
HDAudioRegWriteU32(ISTR0 + STRBDPL, hda.istr0_bdl(I64).u32[0]);
|
||||
HDAudioRegWriteU32(ISTR0 + STRBDPU, hda.istr0_bdl(I64).u32[1]);
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
hda.istr0_bdl[i].buf = hda.istr0_buf[i] = CAllocAligned(SND_BUF_LEN * sizeof(SND_IN_CONTAINER), 128, hda.hc);
|
||||
hda.istr0_bdl[i].len = SND_BUF_LEN * sizeof(SND_IN_CONTAINER);
|
||||
hda.istr0_bdl[i].ctrl = 1;
|
||||
}
|
||||
|
||||
w = HDAudioRegReadU16(HD_STATESTS);
|
||||
while (w)
|
||||
{
|
||||
hda.cad = Bsf(w);
|
||||
if (HDTestCORBSync(hda.cad, 0, VERB_GET_PARAM + P_SUBNODE_CNT))
|
||||
{
|
||||
HDTraverse(hda.cad, 0);
|
||||
|
||||
HDAudioRegWriteU32(OSTR0 + STRLPIB, 0);
|
||||
HDAudioRegWriteU32(OSTR0 + STRCBL, HD_POS_BUF_MULTIPLES * SND_BUF_LEN * sizeof(SND_OUT_CONTAINER));
|
||||
HDAudioRegWriteU16(OSTR0 + STRLVI, 1); //last valid idx // ??
|
||||
HDAudioRegWriteU16(OSTR0 + STRFMT, HD_DEFAULT_OUT_FMT);
|
||||
|
||||
HDAudioRegWriteU32(ISTR0 + STRLPIB, 0);
|
||||
HDAudioRegWriteU32(ISTR0 + STRCBL, HD_POS_BUF_MULTIPLES * SND_BUF_LEN * sizeof(SND_IN_CONTAINER));
|
||||
HDAudioRegWriteU16(ISTR0 + STRLVI, 1); //last valid idx // ??
|
||||
HDAudioRegWriteU16(ISTR0 + STRFMT, HD_DEFAULT_IN_FMT);
|
||||
|
||||
LBts(&sys_semas[SEMA_SOUND], 0); //turn off until cfg completed
|
||||
LBtr(&snd_flags, Sf_FILLING_OUT);
|
||||
hda.audio_task_started = FALSE;
|
||||
if (mp_count > 1)
|
||||
hda.task = Spawn(&HDAudioTask, NULL, "HD Audio", mp_count - 1);
|
||||
else
|
||||
hda.task = Spawn(&HDAudioTask, NULL, "HD Audio");
|
||||
while (!hda.audio_task_started)
|
||||
Yield;
|
||||
snd_dev = SD_HD_AUDIO;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Btr(&w, hda.cad);
|
||||
}
|
||||
|
||||
HDAudioEnd(FALSE);
|
||||
}
|
||||
else
|
||||
hda.bar = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool HDAudioScan()
|
||||
{
|
||||
I64 i = -1, bdf;
|
||||
while (TRUE)
|
||||
{
|
||||
bdf = PCIClassFind(PCIC_MULTIMEDIA << 16 | PCISC_AUDIO << 8, ++i);
|
||||
if (bdf < 0)
|
||||
return FALSE;
|
||||
|
||||
if (HDAudioInit(bdf.u8[2], bdf.u8[1], bdf.u8[0]))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
HDAudioScan;
|
||||
|
||||
#help_index ""
|
720
src/Home/Sound/HDAudio1/Sup1HDAudio/HDCfg.ZC
Normal file
720
src/Home/Sound/HDAudio1/Sup1HDAudio/HDCfg.ZC
Normal file
|
@ -0,0 +1,720 @@
|
|||
|
||||
#define CONNECTS_NUM 16
|
||||
|
||||
class MyMass: CMass
|
||||
{
|
||||
F64 radius;
|
||||
U8 nid, type, num_connects, cur_connect;
|
||||
U32 audio_widget_capabilities;
|
||||
U8 connect_lst[CONNECTS_NUM];
|
||||
U8 gain_lst[CONNECTS_NUM];
|
||||
U32 pin_capabilities, pin_sense,
|
||||
pcm_size_rates,
|
||||
in_amp_cap, out_amp_cap;
|
||||
U8 pin_widget_ctl;
|
||||
Bool disabled;
|
||||
};
|
||||
|
||||
class MySpring: CSpring
|
||||
{
|
||||
I64 color;
|
||||
};
|
||||
|
||||
CMathODE *ode = NULL;
|
||||
|
||||
#define BORDER 10
|
||||
|
||||
U0 DrawIt(CTask *task, CDC *dc)
|
||||
{
|
||||
Bool old_suspend;
|
||||
I16 * buf;
|
||||
I64 i, cxx, cyy,
|
||||
cy = task->pix_height >> 1;
|
||||
F64 dx, dy, d;
|
||||
MyMass * tmpm;
|
||||
MySpring * tmps;
|
||||
|
||||
old_suspend = Suspend(task);
|
||||
tmps = ode->next_spring;
|
||||
while (tmps != &ode->next_spring)
|
||||
{
|
||||
dc->color = tmps->color;
|
||||
GrLine(dc, tmps->end1->x, tmps->end1->y,
|
||||
tmps->end2->x, tmps->end2->y);
|
||||
cxx = (tmps->end1->x + tmps->end2->x) / 2;
|
||||
cyy = (tmps->end1->y + tmps->end2->y) / 2;
|
||||
dx = tmps->end1->x - tmps->end2->x;
|
||||
dy = tmps->end1->y - tmps->end2->y;
|
||||
d = Sqrt(dx *dx + dy *dy);
|
||||
dx /= d;
|
||||
dy /= d;
|
||||
GrLine(dc, cxx, cyy, cxx + 3.0 *dy - 3.0 *dx, cyy - 3.0 *dx - 3.0 *dy);
|
||||
GrLine(dc, cxx, cyy, cxx - 3.0 *dy - 3.0 *dx, cyy + 3.0 *dx - 3.0 *dy);
|
||||
tmps = tmps->next;
|
||||
}
|
||||
|
||||
tmpm = ode->next_mass;
|
||||
while (tmpm != &ode->next_mass)
|
||||
{
|
||||
if (tmpm->disabled)
|
||||
dc->color = BLUE;
|
||||
else
|
||||
dc->color = LTBLUE;
|
||||
GrCircle(dc, tmpm->x, tmpm->y, tmpm->radius);
|
||||
GrPrint(dc, tmpm->x, tmpm->y - FONT_HEIGHT / 2, "%02X%3tZ",
|
||||
tmpm->nid, tmpm->type,
|
||||
"ST_AUDIO_WIDGET_TYPES");
|
||||
tmpm = tmpm->next;
|
||||
}
|
||||
|
||||
Suspend(task, old_suspend);
|
||||
dc->color = BLUE;
|
||||
buf = hda.istr0_buf[0];
|
||||
for (i = 0; i < SND_BUF_LEN; i++)
|
||||
GrPlot(dc, i *task->pix_width / SND_BUF_LEN,
|
||||
cy - buf[i] *cy / I16_MAX);
|
||||
}
|
||||
|
||||
U0 MyDerivative(CMathODE *ode, F64, COrder2D3 *, COrder2D3 *)
|
||||
{
|
||||
//The forces due to springs and drag are
|
||||
//automatically handled by the
|
||||
//ode code.We can add new forces
|
||||
//here.
|
||||
CTask *task = ode->win_task;
|
||||
I64 h = task->pix_width, v = task->pix_height;
|
||||
F64 d, dd;
|
||||
CD3 p;
|
||||
MyMass *tmpm1, *tmpm2;
|
||||
|
||||
tmpm1 = ode->next_mass;
|
||||
while (tmpm1 != &ode->next_mass)
|
||||
{
|
||||
tmpm2 = tmpm1->next;
|
||||
while (tmpm2 != &ode->next_mass)
|
||||
{
|
||||
D3Sub(&p, &tmpm2->state->x, &tmpm1->state->x);
|
||||
dd = D3NormSqr(&p);
|
||||
if (dd <= Sqr(tmpm1->radius + tmpm2->radius))
|
||||
{
|
||||
d = Sqrt(dd) + 0.0001;
|
||||
dd = 10.0* Sqr(Sqr(Sqr(tmpm1->radius + tmpm2->radius) - dd));
|
||||
D3MulEqu(&p, dd / d);
|
||||
D3AddEqu(&tmpm2->DstateDt->DxDt, &p);
|
||||
D3SubEqu(&tmpm1->DstateDt->DxDt, &p);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3MulEqu(&p, 100000.0 / dd);
|
||||
D3AddEqu(&tmpm2->DstateDt->DxDt, &p);
|
||||
D3SubEqu(&tmpm1->DstateDt->DxDt, &p);
|
||||
}
|
||||
|
||||
tmpm2 = tmpm2->next;
|
||||
}
|
||||
|
||||
if (tmpm1->state->x < BORDER)
|
||||
tmpm1->DstateDt->DxDt += 1000* Sqr(tmpm1->state->x - BORDER);
|
||||
if (tmpm1->state->y < BORDER)
|
||||
tmpm1->DstateDt->DyDt += 1000* Sqr(tmpm1->state->y - BORDER);
|
||||
if (tmpm1->state->x > h - BORDER - FONT_WIDTH *6)
|
||||
tmpm1->DstateDt->DxDt -= 1000 *
|
||||
Sqr(tmpm1->state->x - (h - BORDER - FONT_WIDTH *6));
|
||||
if (tmpm1->state->y > v - BORDER)
|
||||
tmpm1->DstateDt->DyDt -= 1000* Sqr(tmpm1->state->y - (v - BORDER));
|
||||
tmpm1 = tmpm1->next;
|
||||
}
|
||||
}
|
||||
|
||||
MyMass* PlaceMass(I64 nid)
|
||||
{
|
||||
MyMass *tmpm = CAlloc(sizeof(MyMass));
|
||||
tmpm->mass = 1.0;
|
||||
tmpm->drag_profile_factor = 100.0;
|
||||
tmpm->radius = 5;
|
||||
tmpm->nid = nid;
|
||||
tmpm->gain_lst[0] = 0x7F;
|
||||
MemSet(tmpm->gain_lst + 1, 0x80, (CONNECTS_NUM - 1) *sizeof(U8));
|
||||
QueueInsert(tmpm, ode->last_mass);
|
||||
return tmpm;
|
||||
}
|
||||
|
||||
MyMass* FindMassByNID(I64 nid)
|
||||
{
|
||||
MyMass * tmpm;
|
||||
tmpm = ode->next_mass;
|
||||
while (tmpm != &ode->next_mass)
|
||||
{
|
||||
if (tmpm->nid == nid)
|
||||
return tmpm;
|
||||
tmpm = tmpm->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MyMass* FindMassByXY(I64 x, I64 y)
|
||||
{
|
||||
I64 dd, best_dd = I64_MAX;
|
||||
MyMass *tmpm, *res = NULL;
|
||||
tmpm = ode->next_mass;
|
||||
while (tmpm != &ode->next_mass)
|
||||
{
|
||||
dd = SqrI64(tmpm->x - x) + SqrI64(tmpm->y - y);
|
||||
if (dd < best_dd)
|
||||
{
|
||||
res = tmpm;
|
||||
best_dd = dd;
|
||||
}
|
||||
|
||||
tmpm = tmpm->next;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 FindConnectIndex(MyMass *tmpm, I64 nid)
|
||||
{
|
||||
I64 i;
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
if (tmpm->connect_lst[i] == nid)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
MySpring* PlaceSpring(MyMass *tmpm1, MyMass *tmpm2)
|
||||
{
|
||||
MySpring *tmps = CAlloc(sizeof(MySpring));
|
||||
tmps->end1 = tmpm1;
|
||||
tmps->end2 = tmpm2;
|
||||
tmps->const = 10;
|
||||
tmps->rest_len = 0;
|
||||
tmps->color = LTGRAY;
|
||||
QueueInsert(tmps, ode->last_spring);
|
||||
return tmps;
|
||||
}
|
||||
|
||||
U0 RedoSprings()
|
||||
{
|
||||
I64 i, k;
|
||||
MyMass *tmpm, *tmpm1;
|
||||
MySpring * tmps;
|
||||
|
||||
QueueDel(&ode->next_spring, TRUE);
|
||||
tmpm = ode->next_mass;
|
||||
while (tmpm != &ode->next_mass)
|
||||
{
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
{
|
||||
if ((k = tmpm->connect_lst[i]) &&
|
||||
(tmpm1 = FindMassByNID(k)))
|
||||
{
|
||||
tmps = PlaceSpring(tmpm, tmpm1);
|
||||
switch (tmpm->type)
|
||||
{
|
||||
case AWT_MIXER:
|
||||
if (!(tmpm->gain_lst[i] &0x80))
|
||||
{
|
||||
//If not mute
|
||||
tmps->color = GREEN;
|
||||
tmps->const = 100;
|
||||
}
|
||||
|
||||
break;
|
||||
case AWT_INPUT:
|
||||
case AWT_SELECTOR:
|
||||
case AWT_PIN_COMPLEX:
|
||||
case AWT_VENDOR:
|
||||
if (i == tmpm->cur_connect)
|
||||
{
|
||||
tmps->color = RED;
|
||||
tmps->const = 100;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmpm = tmpm->next;
|
||||
}
|
||||
}
|
||||
|
||||
U0 Init()
|
||||
{
|
||||
ode = ODENew(0, 1e-4, ODEF_HAS_MASSES);
|
||||
ode->derive = &MyDerivative;
|
||||
ode->drag_v2 = 0.002;
|
||||
ode->drag_v3 = 0.00001;
|
||||
ode->acceleration_limit = 5e3;
|
||||
|
||||
QueueInsert(ode, Fs->last_ode);
|
||||
}
|
||||
|
||||
U0 CleanUp()
|
||||
{
|
||||
QueueRemove(ode);
|
||||
QueueDel(&ode->next_mass, TRUE);
|
||||
QueueDel(&ode->next_spring, TRUE);
|
||||
ODEDel(ode);
|
||||
}
|
||||
|
||||
U0 HDCfgConnectLst(MyMass *tmpm, I64 cad, I64 nid)
|
||||
{
|
||||
I64 i, j, connection_lst_len;
|
||||
j = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_CONNECT_LST_LEN);
|
||||
connection_lst_len = j &127;
|
||||
if (j & 128)
|
||||
{
|
||||
//Long form?
|
||||
for (i = 0; i < connection_lst_len; i += 2)
|
||||
{
|
||||
j = HDWriteCORBSync(cad, nid, VERB_GET_CONNECT_LST + i);
|
||||
tmpm->connect_lst[tmpm->num_connects++] = j.u16[0];
|
||||
if (i + 1 < connection_lst_len)
|
||||
tmpm->connect_lst[tmpm->num_connects++] = j.u16[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < connection_lst_len; i += 4)
|
||||
{
|
||||
j = HDWriteCORBSync(cad, nid, VERB_GET_CONNECT_LST + i);
|
||||
tmpm->connect_lst[tmpm->num_connects++] = j.u8[0];
|
||||
if (i + 1 < connection_lst_len)
|
||||
tmpm->connect_lst[tmpm->num_connects++] = j.u8[1];
|
||||
if (i + 2 < connection_lst_len)
|
||||
tmpm->connect_lst[tmpm->num_connects++] = j.u8[2];
|
||||
if (i + 3 < connection_lst_len)
|
||||
tmpm->connect_lst[tmpm->num_connects++] = j.u8[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDCfgTraverse(I64 cad, I64 nid)
|
||||
{
|
||||
I64 i, j;
|
||||
MyMass *tmpm = PlaceMass(nid);
|
||||
j = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_SUBNODE_CNT);
|
||||
if (j.u16[0])
|
||||
{
|
||||
tmpm->type = AWT_NODE;
|
||||
for (i = j.u16[1]; i < j.u16[1] + j.u16[0]; i++)
|
||||
HDCfgTraverse(cad, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpm->audio_widget_capabilities =
|
||||
HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_AUDIO_WIDGET_CAP);
|
||||
tmpm->pcm_size_rates =
|
||||
HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_SAMPLE_SIZE_RATE_CAP);
|
||||
tmpm->in_amp_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_INPUT_AMP_CAP);
|
||||
tmpm->out_amp_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_OUTPUT_AMP_CAP);
|
||||
tmpm->type = tmpm->audio_widget_capabilities >> 20 &15;
|
||||
switch (tmpm->type)
|
||||
{
|
||||
case AWT_PIN_COMPLEX:
|
||||
tmpm->pin_widget_ctl =
|
||||
HDWriteCORBSync(cad, nid, VERB_PIN_WIDGET_CTL_GET);
|
||||
tmpm->pin_capabilities =
|
||||
HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_PIN_CAP);
|
||||
if (Bt(&tmpm->pin_capabilities, 0) ||
|
||||
Bt(&tmpm->pin_capabilities, 2))
|
||||
tmpm->pin_sense = HDWriteCORBSync(cad, nid, VERB_PIN_SENSE_GET);
|
||||
HDWriteCORBSync(cad, nid, VERB_CONNECT_SEL_SET + 0x00);
|
||||
break;
|
||||
case AWT_INPUT:
|
||||
tmpm->disabled = TRUE;
|
||||
case AWT_SELECTOR:
|
||||
case AWT_VENDOR:
|
||||
HDWriteCORBSync(cad, nid, VERB_CONNECT_SEL_SET + 0x00);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Bt(&tmpm->audio_widget_capabilities, 8))
|
||||
HDCfgConnectLst(tmpm, cad, nid);
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDCfgRandomizeXY()
|
||||
{
|
||||
I64 h = Fs->pix_width, v = Fs->pix_height;
|
||||
MyMass * tmpm;
|
||||
tmpm = ode->next_mass;
|
||||
while (tmpm != &ode->next_mass)
|
||||
{
|
||||
tmpm->x = RandU32 % (h - 2 *BORDER - FONT_WIDTH *6) + BORDER;
|
||||
tmpm->y = RandU32 % (v - 2 *BORDER) + BORDER;
|
||||
tmpm = tmpm->next;
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDCfgPopUpInfoTask(MyMass *tmpm)
|
||||
{
|
||||
I64 i;
|
||||
"$$FG,RED$$NID:$$FG$$0x%02X$$FG,RED$$Type:$$FG$$%Z\n",
|
||||
tmpm->nid, tmpm->type, "ST_AUDIO_WIDGET_TYPES";
|
||||
|
||||
i = tmpm->audio_widget_capabilities;
|
||||
"\n$$FG,RED$$Audio Widget Capabilities:$$FG$$\n";
|
||||
if (Bt(&i, 0))
|
||||
"Stereo,";
|
||||
if (Bt(&i, 1))
|
||||
"In Amp,";
|
||||
if (Bt(&i, 2))
|
||||
"Out Amp,";
|
||||
if (Bt(&i, 3))
|
||||
"AmpOverride,";
|
||||
if (Bt(&i, 4))
|
||||
"FmtOverride,";
|
||||
if (Bt(&i, 5))
|
||||
"Stripe,";
|
||||
if (Bt(&i, 6))
|
||||
"Proc Wgt,";
|
||||
if (Bt(&i, 7))
|
||||
"Unsolicited,";
|
||||
if (Bt(&i, 8))
|
||||
"Cnt Lst,";
|
||||
if (Bt(&i, 9))
|
||||
"Digital,";
|
||||
if (Bt(&i, 10))
|
||||
"Power Ctrl,";
|
||||
if (Bt(&i, 11))
|
||||
"Left/Right Swap,";
|
||||
"Delay:%d\n", i.u16[1] &0xF;
|
||||
|
||||
i = tmpm->in_amp_cap;
|
||||
"\n$$FG,RED$$Input Amp Capabilities:$$FG$$\n"
|
||||
"Offset:0x%02X Steps:0x%02X StepSize:%5.2fdB Mutable:%d\n",
|
||||
i &127, i.u8[1] &127 + 1, 0.25 *(i.u16[1] &127), Bt(&i, 31);
|
||||
|
||||
i = tmpm->out_amp_cap;
|
||||
"\n$$FG,RED$$Output Amp Capabilities:$$FG$$\n"
|
||||
"Offset:0x%02X Steps:0x%02X StepSize:%5.2fdB Mutable:%d\n",
|
||||
i &127, i.u8[1] &127 + 1, 0.25 *(i.u16[1] &127), Bt(&i, 31);
|
||||
|
||||
"\n$$FG,RED$$Size Rates Capabilities:$$FG$$\n";
|
||||
for (i = 0; i < 21; i++)
|
||||
if (Bt(&tmpm->pcm_size_rates, i))
|
||||
"%z", i,
|
||||
" 8.0kHz\0 11.025kHz\0 16.0kHz\0 22.05kHz\0"
|
||||
" 32.0kHz\0 44.1kHz\0 48.0kHz\0 88.2kHz\0"
|
||||
" 96.0kHz\0 176.4kHz\0 192.0kHz\0 384kHz\0"
|
||||
"\0\0\0\0"
|
||||
" 8Bit\0 16bit\0 20Bit\0 24Bit\0 32Bit\0";
|
||||
'\n';
|
||||
|
||||
"\n$$FG,RED$$Connection Lst:$$FG$$\n";
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
"%02X,", tmpm->connect_lst[i];
|
||||
'\n';
|
||||
|
||||
"\n$$FG,RED$$Gain Lst:$$FG$$\n";
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
"%02X,", tmpm->gain_lst[i];
|
||||
'\n';
|
||||
|
||||
switch (tmpm->type)
|
||||
{
|
||||
case AWT_PIN_COMPLEX:
|
||||
"\n$$FG,RED$$Pin Capabilities:$$FG$$\n";
|
||||
i = tmpm->pin_capabilities;
|
||||
if (Bt(&i, 0))
|
||||
"Impedance Sense,";
|
||||
if (Bt(&i, 1))
|
||||
"Trigger Required,";
|
||||
if (Bt(&i, 2))
|
||||
"Presence Detect,";
|
||||
if (Bt(&i, 3))
|
||||
"Headphone Drive,";
|
||||
if (Bt(&i, 4))
|
||||
"Output,";
|
||||
if (Bt(&i, 5))
|
||||
"Input,";
|
||||
if (Bt(&i, 6))
|
||||
"Balanced,";
|
||||
if (Bt(&i, 16))
|
||||
"EAPD,";
|
||||
"Vref:%02X\n\n", i.u8[1];
|
||||
if (Bt(&tmpm->pin_capabilities, 0) ||
|
||||
Bt(&tmpm->pin_capabilities, 2))
|
||||
tmpm->pin_sense = HDWriteCORBSync(hda.cad,
|
||||
tmpm->nid, VERB_PIN_SENSE_GET);
|
||||
if (Bt(&tmpm->pin_capabilities, 0))
|
||||
"Impedance Measurement:%08X\n", tmpm->pin_sense &0x7FFFFFFF;
|
||||
if (Bt(&tmpm->pin_capabilities, 2))
|
||||
"Presence:%d\n", Bt(&tmpm->pin_sense, 31);
|
||||
"\n\nPin widget ctrl bits:\n"
|
||||
"7: High phn enable (low impedance output amp)\n"
|
||||
"6: Output Enable\n"
|
||||
"5: Input Enable\n"
|
||||
"0-2: Vref 0=HiZ 1=50% 2=Gnd 4=80% 5=100%\n";
|
||||
tmpm->pin_widget_ctl = I64Get("Widget Ctrl (0x%02X):",
|
||||
tmpm->pin_widget_ctl, 0, 0xFF);
|
||||
HDWriteCORBSync(hda.cad, tmpm->nid,
|
||||
VERB_PIN_WIDGET_CTL_SET + tmpm->pin_widget_ctl);
|
||||
break;
|
||||
case AWT_INPUT:
|
||||
"Disable";
|
||||
if (tmpm->disabled = YorN)
|
||||
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||
else
|
||||
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x20);
|
||||
'\n';
|
||||
break;
|
||||
case AWT_OUTPUT:
|
||||
"Disable";
|
||||
if (tmpm->disabled = YorN)
|
||||
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||
else
|
||||
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x10);
|
||||
'\n';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDCfgPopUpInfo(MyMass *tmpm)
|
||||
{
|
||||
U8 buf[STR_LEN];
|
||||
StrPrint(buf,
|
||||
"HDCfgPopUpInfoTask(0x%X);\"\\n\\nPress SHIFT-ESC\\n\\n\\n\\n\";View;",
|
||||
tmpm);
|
||||
Fs->win_inhibit |= WIF_SELF_ODE;
|
||||
Fs->draw_it = NULL;
|
||||
Refresh;
|
||||
PopUp(buf, Fs);
|
||||
Fs->win_inhibit &= ~WIF_SELF_ODE;
|
||||
Fs->draw_it = &DrawIt;
|
||||
}
|
||||
|
||||
U0 HDCfgEdLink(MyMass *tmpm_out, MyMass *tmpm_in)
|
||||
{
|
||||
I64 i, j;
|
||||
if ((i = FindConnectIndex(tmpm_in, tmpm_out->nid)) >= 0)
|
||||
{
|
||||
switch (tmpm_in->type)
|
||||
{
|
||||
case AWT_MIXER:
|
||||
MemSet(tmpm_in->gain_lst, 0x80, sizeof(U8) *CONNECTS_NUM);
|
||||
tmpm_in->gain_lst[i] = 0x7F;
|
||||
for (j = 0; j < tmpm_in->num_connects; j++)
|
||||
HDWriteCORBSync(hda.cad, tmpm_in->nid,
|
||||
VERB_AMPLIFIER_GAIN_SET + 0x7000 + tmpm_in->gain_lst[j] + j << 8);
|
||||
break;
|
||||
case AWT_INPUT:
|
||||
case AWT_SELECTOR:
|
||||
case AWT_PIN_COMPLEX:
|
||||
case AWT_VENDOR:
|
||||
tmpm_in->cur_connect = i;
|
||||
HDWriteCORBSync(hda.cad, tmpm_in->nid, VERB_CONNECT_SEL_SET + i);
|
||||
break;
|
||||
}
|
||||
|
||||
RedoSprings;
|
||||
}
|
||||
}
|
||||
|
||||
U0 HDCfgSave()
|
||||
{
|
||||
CDoc *doc = DocNew;
|
||||
I64 i;
|
||||
MyMass * tmpm;
|
||||
DocPrint(doc, "//This file was generated by "
|
||||
"$$LK,\"::/TempleOS/Adam/Sound/HDCfg.ZC.Z\","
|
||||
"\"FI:::/TempleOS/Adam/Sound/HDCfg.ZC\"$$\n\n"
|
||||
"U0 MyHDCfg()\n{\n");
|
||||
tmpm = ode->next_mass;
|
||||
while (tmpm != &ode->next_mass)
|
||||
{
|
||||
DocPrint(doc, " //0x%02X %Z\n", tmpm->nid, tmpm->type,
|
||||
"ST_AUDIO_WIDGET_TYPES");
|
||||
if (tmpm->num_connects)
|
||||
{
|
||||
DocPrint(doc, "//Connection Lst:");
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
{
|
||||
if (i == tmpm->cur_connect)
|
||||
DocPrint(doc, "*");
|
||||
DocPrint(doc, "0x%02X ", tmpm->connect_lst[i]);
|
||||
}
|
||||
|
||||
DocPrint(doc, "\n");
|
||||
if (tmpm->type == AWT_MIXER)
|
||||
{
|
||||
DocPrint(doc, "//Gain Lst:");
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
DocPrint(doc, "0x%02X ", tmpm->gain_lst[i]);
|
||||
DocPrint(doc, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
switch (tmpm->type)
|
||||
{
|
||||
case AWT_OUTPUT:
|
||||
if (tmpm->disabled)
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_CHAN_STREAM_ID_SET+0x00);\n",
|
||||
tmpm->nid);
|
||||
else
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_CHAN_STREAM_ID_SET+0x10);\n",
|
||||
tmpm->nid);
|
||||
break;
|
||||
case AWT_MIXER:
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_AMPLIFIER_GAIN_SET+0xB07F);\n",
|
||||
tmpm->nid);
|
||||
for (i = 0; i < tmpm->num_connects; i++)
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_AMPLIFIER_GAIN_SET+0x%04X);\n",
|
||||
tmpm->nid, 0x7000 + tmpm->gain_lst[i] + i << 8);
|
||||
break;
|
||||
case AWT_INPUT:
|
||||
if (tmpm->disabled)
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_CHAN_STREAM_ID_SET+0x00);\n",
|
||||
tmpm->nid);
|
||||
else
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_CHAN_STREAM_ID_SET+0x20);\n",
|
||||
tmpm->nid);
|
||||
goto here;
|
||||
case AWT_PIN_COMPLEX:
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_PIN_WIDGET_CTL_SET+0x%02X);\n",
|
||||
tmpm->nid, tmpm->pin_widget_ctl);
|
||||
case AWT_SELECTOR:
|
||||
case AWT_VENDOR:
|
||||
here:
|
||||
if (tmpm->num_connects > 1)
|
||||
DocPrint(doc,
|
||||
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||
"VERB_CONNECT_SEL_SET+0x%02X);\n",
|
||||
tmpm->nid, tmpm->cur_connect);
|
||||
break;
|
||||
}
|
||||
|
||||
DocPrint(doc, "\n");
|
||||
tmpm = tmpm->next;
|
||||
}
|
||||
|
||||
DocPrint(doc, "LBtr(&sys_semas[SEMA_SND],0);\n"
|
||||
"}\n\nif (snd_dev==SD_HD_AUDIO)\n"
|
||||
"MyHDCfg;\n");
|
||||
StrCopy(doc->filename.name, "~/HDAudioCfg.ZC.Z");
|
||||
DocWrite(doc);
|
||||
DocDel(doc);
|
||||
}
|
||||
|
||||
U0 HDCfg()
|
||||
{
|
||||
I64 arg1, arg2;
|
||||
MyMass *tmpm1 = NULL, *tmpm2 = NULL;
|
||||
|
||||
if (snd_dev != SD_HD_AUDIO)
|
||||
{
|
||||
"HD Audio not detected\n";
|
||||
return;
|
||||
}
|
||||
MenuPush( "File {"
|
||||
" Abort(,CH_SHIFT_ESC);"
|
||||
" Exit(,CH_ESC);"
|
||||
"}"
|
||||
"Edit {"
|
||||
" Randomize(,'\n');"
|
||||
" Options(,CH_SPACE);"
|
||||
"}"
|
||||
);
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
DocBottom;
|
||||
AutoComplete;
|
||||
WinBorder;
|
||||
WinMax;
|
||||
DocCursor;
|
||||
DocClear;
|
||||
Fs->win_inhibit = WIF_SELF_MS_L | WIF_SELF_MS_R | WIG_DBL_CLICK | WIF_SELF_DOC;
|
||||
Init;
|
||||
|
||||
HDCfgTraverse(hda.cad, 0);
|
||||
HDCfgRandomizeXY;
|
||||
RedoSprings;
|
||||
Fs->draw_it = &DrawIt;
|
||||
PopUpOk( "This is a tool to cfgure\n"
|
||||
"HD Audio.It creates $$FG,RED$$~/HDAudioCfg.ZC.Z$$FG$$\n"
|
||||
"which you should $$FG,GREEN$$
|
||||
#include$$FG$$ in your\n"
|
||||
"$$FG,RED$$~/HomeSnd.ZC.Z$$FG$$ file.\n\n\n"
|
||||
"Left click to see info and cfgure a widget.\n"
|
||||
"Right click drag to connect output to input.\n\n"
|
||||
"You will need to set input and output amplifier\n"
|
||||
"gains by hand -- edit $$FG,RED$$~/HDAudioCfg.ZC.Z$$FG$$.\n\n"
|
||||
"The $$FG,BLUE$$BLUE$$FG$$ line in the middle is microphone waveform.\n\n"
|
||||
);
|
||||
|
||||
HDRun(TRUE, TRUE); //run input output
|
||||
|
||||
try
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
switch (MessageGet(&arg1, &arg2,
|
||||
1 << MESSAGE_MS_L_UP | 1 << MESSAGE_MS_R_DOWN | 1 << MESSAGE_MS_R_UP | 1 << MESSAGE_KEY_DOWN))
|
||||
{
|
||||
case MESSAGE_MS_L_UP:
|
||||
if (tmpm1 = FindMassByXY(arg1, arg2))
|
||||
HDCfgPopUpInfo(tmpm1);
|
||||
tmpm1 = NULL;
|
||||
break;
|
||||
case MESSAGE_MS_R_DOWN:
|
||||
tmpm1 = FindMassByXY(arg1, arg2);
|
||||
break;
|
||||
case MESSAGE_MS_R_UP:
|
||||
tmpm2 = FindMassByXY(arg1, arg2);
|
||||
if (tmpm1 && tmpm2)
|
||||
HDCfgEdLink(tmpm1, tmpm2);
|
||||
break;
|
||||
case MESSAGE_KEY_DOWN:
|
||||
switch (arg1)
|
||||
{
|
||||
case CH_SPACE:
|
||||
if (tmpm1 = FindMassByXY( mouse.pos.x - Fs->pix_left - Fs->scroll_x,
|
||||
mouse.pos.y - Fs->pix_top - Fs->scroll_y))
|
||||
HDCfgPopUpInfo(tmpm1);
|
||||
tmpm1 = NULL;
|
||||
break;
|
||||
case '\n':
|
||||
HDCfgRandomizeXY;
|
||||
break;
|
||||
case CH_ESC:
|
||||
HDCfgSave;
|
||||
case CH_SHIFT_ESC:
|
||||
goto hd_done;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hd_done: //Don't goto out of try
|
||||
MessageGet(,, 1 << MESSAGE_KEY_UP);
|
||||
}
|
||||
|
||||
catch
|
||||
Fs->catch_except = TRUE;
|
||||
SettingsPop;
|
||||
HDStop(TRUE, FALSE); //stop input
|
||||
CleanUp;
|
||||
MenuPop;
|
||||
"$$BK,1$$Note:
|
||||
#include \"~/HDAudioCfg\" in your start-up scripts."
|
||||
"$$BK,0$$\n";
|
||||
}
|
||||
|
||||
HDCfg;
|
21
src/Home/Sound/HDAudio1/Sup1Snd/MakeSnd.ZC
Normal file
21
src/Home/Sound/HDAudio1/Sup1Snd/MakeSnd.ZC
Normal file
|
@ -0,0 +1,21 @@
|
|||
Cd(__DIR__);;
|
||||
|
||||
#help_index "Sound"
|
||||
class CSndWaveCtrl
|
||||
{
|
||||
I64 sample_rate,sample_bits,channels;
|
||||
F64 freq_multiplier,amp_multiplier;
|
||||
F64 phase,last_y,last_dydt,next_y;
|
||||
};
|
||||
|
||||
public U0 SoundTaskEndCB()
|
||||
{//Will turn-off snd when a task gets killed.
|
||||
Sound;
|
||||
Exit;
|
||||
}
|
||||
|
||||
#include "SndMath"
|
||||
#include "SndMusic"
|
||||
#include "SndEffects"
|
||||
#include "SndFile"
|
||||
Cd("..");;
|
80
src/Home/Sound/HDAudio1/Sup1Snd/SndEffects.ZC
Normal file
80
src/Home/Sound/HDAudio1/Sup1Snd/SndEffects.ZC
Normal file
|
@ -0,0 +1,80 @@
|
|||
#help_index "Sound"
|
||||
|
||||
#define SE_NOISE 0
|
||||
#define SE_SWEEP 1
|
||||
|
||||
class CSoundEffectFrame
|
||||
{
|
||||
I32 type;
|
||||
I8 ona1,ona2;
|
||||
F64 duration;
|
||||
};
|
||||
|
||||
U0 SoundEffectEndTaskCB()
|
||||
{
|
||||
Free(FramePtr("CSoundEffectFrame"));
|
||||
music.mute--;
|
||||
SoundTaskEndCB;
|
||||
}
|
||||
|
||||
U0 SoundEffectTask(CSoundEffectFrame *ns)
|
||||
{
|
||||
I64 i,ona;
|
||||
F64 t0=tS,t,timeout=t0+ns->duration;
|
||||
FramePtrAdd("CSoundEffectFrame",ns);
|
||||
Fs->task_end_cb=&SoundEffectEndTaskCB;
|
||||
switch (ns->type) {
|
||||
case SE_NOISE:
|
||||
i=MaxI64(ns->ona2-ns->ona1,1);
|
||||
while (tS<timeout) {
|
||||
ona=RandU16%i+ns->ona1;
|
||||
Sound(ona);
|
||||
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
|
||||
if (t+tS>timeout)
|
||||
t=timeout-tS;
|
||||
Sleep(t);
|
||||
}
|
||||
break;
|
||||
case SE_SWEEP:
|
||||
while (tS<timeout) {
|
||||
t=(tS-t0)/ns->duration;
|
||||
ona=(1.0-t)*ns->ona1+t*ns->ona2;
|
||||
Sound(ona);
|
||||
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
|
||||
if (t+tS>timeout)
|
||||
t=timeout-tS;
|
||||
Sleep(t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public CTask *Noise(I64 mS,F64 min_ona,F64 max_ona)
|
||||
{//Make white noise for given number of mS.
|
||||
CSoundEffectFrame *ns;
|
||||
if (mS>0) {
|
||||
ns=MAlloc(sizeof(CSoundEffectFrame));
|
||||
ns->type=SE_NOISE;
|
||||
ns->duration=mS/1000.0;
|
||||
ns->ona1=min_ona;
|
||||
ns->ona2=max_ona;
|
||||
music.mute++;
|
||||
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public CTask *Sweep(I64 mS,F64 ona1,F64 ona2)
|
||||
{//Sweep through freq range in given number of mS.
|
||||
CSoundEffectFrame *ns;
|
||||
if (mS>0) {
|
||||
ns=MAlloc(sizeof(CSoundEffectFrame));
|
||||
ns->type=SE_SWEEP;
|
||||
ns->duration=mS/1000.0;
|
||||
ns->ona1=ona1;
|
||||
ns->ona2=ona2;
|
||||
music.mute++;
|
||||
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
|
||||
} else
|
||||
return NULL;
|
||||
}
|
137
src/Home/Sound/HDAudio1/Sup1Snd/SndFile.ZC
Normal file
137
src/Home/Sound/HDAudio1/Sup1Snd/SndFile.ZC
Normal file
|
@ -0,0 +1,137 @@
|
|||
#help_index "Sound/Sound Files"
|
||||
#define SNDFILE_SAMPLE_RATE 8000
|
||||
//Header for a ".SND" file
|
||||
class CFileSND
|
||||
{//big endian
|
||||
U32 signature; //0x646e732e
|
||||
U32 offset; //24
|
||||
U32 data_size;
|
||||
U32 coding; //3=16bit uncompressed
|
||||
U32 sample_rate; //Hz
|
||||
U32 channels; //1=mono
|
||||
I16 body[1];
|
||||
};
|
||||
|
||||
//Windows media constraint.
|
||||
//#define SND_FILE_DATA_MAX 0x0007FF00
|
||||
#define SND_FILE_DATA_MAX 0x7FFFFF00
|
||||
|
||||
public I64 SndFileCreate(U8 *base_filename,F64 normalized_vol=1.0,
|
||||
F64 averaging=0.0,I64 waveform=WF_SQUARE,
|
||||
F64 reverb_delay=0,F64 reverb_intensity=0,F64 time_shift=0)
|
||||
{//Use "screencast.record" flag to start or stop recording, then call this routine.
|
||||
//Averaging should be a num from 0.0 to 0.999.
|
||||
//Vol should be from 0.0 to 1.0.
|
||||
//Set reverb_delay to like 0.3 sec and reverb_intensity to like 0.4.
|
||||
I64 i,i1,k,cnt,cnt2,level,file_num;
|
||||
F64 avg,dt;
|
||||
CFileSND *s;
|
||||
CSndWaveCtrl *swc=SndWaveCtrlNew(SNDFILE_SAMPLE_RATE,16,1);
|
||||
CSoundData *d,*d1;
|
||||
U8 *name,*name2;
|
||||
|
||||
screencast.record=FALSE;
|
||||
|
||||
dt=screencast.sound_head.last->tS-screencast.sound_head.next->tS;
|
||||
if (!dt) return 0;
|
||||
cnt=dt*SNDFILE_SAMPLE_RATE;
|
||||
cnt++; //Terminator
|
||||
|
||||
name=StrNew(base_filename);
|
||||
FileExtRemove(name);
|
||||
|
||||
s=CAlloc(offset(CFileSND.body)+cnt*sizeof(I16));
|
||||
s->signature=0x646e732e;
|
||||
s->offset=EndianU32(offset(CFileSND.body));
|
||||
s->coding=EndianU32(3);
|
||||
s->sample_rate=EndianU32(SNDFILE_SAMPLE_RATE);
|
||||
s->channels=EndianU32(1);
|
||||
|
||||
if (time_shift) {
|
||||
d=screencast.sound_head.next;
|
||||
d->tS-=time_shift;
|
||||
while (d->next!=&screencast.sound_head) {
|
||||
d1=d->next;
|
||||
dt=d1->tS-d->tS;
|
||||
if (dt<0) {
|
||||
QueueRemove(d1);
|
||||
Free(d1);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d=screencast.sound_head.next;
|
||||
k=0;
|
||||
i=d->tS*SNDFILE_SAMPLE_RATE;
|
||||
while (d->next!=&screencast.sound_head) {
|
||||
d1=d->next;
|
||||
i1=d1->tS*SNDFILE_SAMPLE_RATE;
|
||||
if (i1-i) {
|
||||
SndWaveAddBuf(swc,&s->body[k],i1-i,
|
||||
Ona2Freq(d->ona),waveform,normalized_vol);
|
||||
k+=i1-i;
|
||||
i=i1;
|
||||
}
|
||||
QueueRemove(d);
|
||||
Free(d);
|
||||
d=d1;
|
||||
}
|
||||
|
||||
//Average
|
||||
if (averaging) {
|
||||
avg=0;
|
||||
for (i=0;i<cnt-1;i++)
|
||||
s->body[i]=avg=LowPass1(averaging,avg,s->body[i],1.0);
|
||||
}
|
||||
|
||||
//Reverb
|
||||
if (reverb_intensity) {
|
||||
if (dt=reverb_delay*SNDFILE_SAMPLE_RATE)
|
||||
for (i=dt;i<cnt;i++)
|
||||
s->body[i]+=reverb_intensity*s->body[i-dt];
|
||||
}
|
||||
|
||||
//Get rid of D.C. component
|
||||
for (k=0;k<3;k++) {
|
||||
level=0;
|
||||
for (i=0;i<cnt-1;i++)
|
||||
level+=s->body[i];
|
||||
level/=cnt-1;
|
||||
for (i=0;i<cnt-1;i++)
|
||||
s->body[i]=ClampI64(s->body[i]-level,I16_MIN,I16_MAX);
|
||||
}
|
||||
|
||||
for (i=0;i<cnt-1;i++)
|
||||
s->body[i]=EndianU16(s->body[i]);
|
||||
|
||||
s->body[cnt-1]=0;
|
||||
|
||||
d=screencast.sound_head.next;
|
||||
while (d!=&screencast.sound_head) {
|
||||
d1=d->next;
|
||||
QueueRemove(d);
|
||||
Free(d);
|
||||
d=d1;
|
||||
}
|
||||
|
||||
name2=MAlloc(StrLen(name)+3+1+3+1);
|
||||
cnt2=cnt;
|
||||
file_num=0;
|
||||
while (cnt2>0) {
|
||||
i=cnt2;
|
||||
if (i>SND_FILE_DATA_MAX)
|
||||
i=SND_FILE_DATA_MAX;
|
||||
s->data_size=EndianU32(i*sizeof(I16));
|
||||
MemCopy(s->body,&s->body[file_num*SND_FILE_DATA_MAX],i*sizeof(I16));
|
||||
StrPrint(name2,"%s%03d.SND",name,file_num++);
|
||||
FileWrite(name2,s,offset(CFileSND.body)+i*sizeof(I16));
|
||||
cnt2-=i;
|
||||
}
|
||||
Free(s);
|
||||
Free(name);
|
||||
Free(name2);
|
||||
|
||||
SndWaveCtrlDel(swc);
|
||||
return cnt;
|
||||
}
|
248
src/Home/Sound/HDAudio1/Sup1Snd/SndMath.ZC
Normal file
248
src/Home/Sound/HDAudio1/Sup1Snd/SndMath.ZC
Normal file
|
@ -0,0 +1,248 @@
|
|||
#help_index "Sound/Math;Math"
|
||||
public F64 Saw(F64 t,F64 period)
|
||||
{//Sawtooth. 0.0 - 1.0 think "(Sin+1)/2"
|
||||
if (period) {
|
||||
if (t>=0.0)
|
||||
return t%period/period;
|
||||
else
|
||||
return 1.0+t%period/period;
|
||||
} else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public F64 FullSaw(F64 t,F64 period)
|
||||
{//Plus&Minus Sawtooth. 1.0 - -1.0 think "Sin"
|
||||
if (period) {
|
||||
if (t>=0.0)
|
||||
return 2.0*(t%period/period)-1.0;
|
||||
else
|
||||
return 2.0*(t%period/period)+1.0;
|
||||
} else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public F64 Caw(F64 t,F64 period)
|
||||
{//Cawtooth. 1.0 - 0.0 think "(Cos+1)/2"
|
||||
if (period) {
|
||||
if (t>=0.0)
|
||||
return 1.0-t%period/period;
|
||||
else
|
||||
return -(t%period)/period;
|
||||
} else
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public F64 FullCaw(F64 t,F64 period)
|
||||
{//Plus&Minus Cawtooth. 1.0 - -1.0 think "Cos"
|
||||
if (period) {
|
||||
if (t>=0.0)
|
||||
return -2.0*(t%period/period)+1.0;
|
||||
else
|
||||
return -2.0*(t%period/period)-1.0;
|
||||
} else
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public F64 Tri(F64 t,F64 period)
|
||||
{//Triangle waveform. 0.0 - 1.0 - 0.0
|
||||
if (period) {
|
||||
t=2.0*(Abs(t)%period)/period;
|
||||
if (t<=1.0)
|
||||
return t;
|
||||
else
|
||||
return 2.0-t;
|
||||
} else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public F64 FullTri(F64 t,F64 period)
|
||||
{//Plus&Minus Triangle waveform. 0.0 - 1.0 - 0.0 - -1.0 -0.0
|
||||
if (period) {
|
||||
t=4.0*(t%period)/period;
|
||||
if (t<=-1.0) {
|
||||
if (t<=-3.0)
|
||||
return t+4.0;
|
||||
else
|
||||
return -2.0-t;
|
||||
} else {
|
||||
if (t<=1.0)
|
||||
return t;
|
||||
else if (t<=3.0)
|
||||
return 2.0-t;
|
||||
else
|
||||
return t-4.0;
|
||||
}
|
||||
} else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#help_index "Sound/Math"
|
||||
|
||||
public I8 Note2Ona(I64 note,I64 octave=4)
|
||||
{//Note to ona. Mid C is ona=51, note=3 and octave=4.
|
||||
if (note<3)
|
||||
return (octave+1)*12+note;
|
||||
else
|
||||
return octave*12+note;
|
||||
}
|
||||
|
||||
public I8 Ona2Note(I8 ona)
|
||||
{//Ona to note in octave. Mid C is ona=51, note=3 and octave=4.
|
||||
return ona%12;
|
||||
}
|
||||
|
||||
public I8 Ona2Octave(I8 ona)
|
||||
{//Ona to octave. Mid C is ona=51, note=3 and octave=4.
|
||||
I64 note=ona%12,octave=ona/12;
|
||||
if (note<3)
|
||||
return octave-1;
|
||||
else
|
||||
return octave;
|
||||
}
|
||||
|
||||
F64 SinPhaseCont(F64 last_y,F64 last_dydt,
|
||||
F64 current_amp,F64 phase_offset)
|
||||
{//Next sample of sin waveform.
|
||||
F64 phase;
|
||||
phase=last_y/current_amp;
|
||||
if (phase>1.0) phase=1.0;
|
||||
if (phase<-1.0) phase=-1.0;
|
||||
if (last_dydt<0)
|
||||
phase=ã-ASin(phase);
|
||||
else
|
||||
phase=ASin(phase);
|
||||
return phase-phase_offset;
|
||||
}
|
||||
|
||||
public CSndWaveCtrl *SndWaveCtrlNew(I64 sample_rate=8000,I64 sample_bits=24,
|
||||
I64 channels=2,CTask *mem_task=NULL)
|
||||
{//MAlloc ctrl struct for generating waveforms.
|
||||
CSndWaveCtrl *swc=CAlloc(sizeof(CSndWaveCtrl),mem_task);
|
||||
swc->freq_multiplier=1.0;
|
||||
swc->amp_multiplier=1.0;
|
||||
swc->sample_rate=sample_rate;
|
||||
swc->sample_bits=sample_bits;
|
||||
swc->channels=channels;
|
||||
swc->last_dydt=1.0;
|
||||
return swc;
|
||||
}
|
||||
|
||||
public U0 SndWaveCtrlDel(CSndWaveCtrl *swc)
|
||||
{//Free waveform ctrl.
|
||||
Free(swc);
|
||||
}
|
||||
|
||||
#define WF_NULL 0
|
||||
#define WF_SQUARE 1
|
||||
#define WF_SINE 2
|
||||
#define WF_TRI 3
|
||||
#define WF_SAWTOOTH 4
|
||||
#define WF_NOISE 5
|
||||
#define WF_WAVEFORMS_NUM 6
|
||||
|
||||
public U0 SndWaveAddBuf(CSndWaveCtrl *swc,U8 *buf,I64 num_samples,
|
||||
F64 _freq,I64 _waveform=WF_SQUARE,F64 _amp=1.0,F64 _left=1.0, F64 _right=1.0)
|
||||
{//Add waveform to buffer.
|
||||
//num_samples is multiplied by channels to get buf_len.
|
||||
//left,right range from 0.0-1.0
|
||||
//Supports 16,24 and 32 bits
|
||||
I64 reg i,reg j,reg k;
|
||||
F64 a,f,amp,reg phase;
|
||||
if (!swc) return;
|
||||
_freq*=swc->freq_multiplier;
|
||||
_amp*=swc->amp_multiplier;
|
||||
if (!_freq||!_amp) {
|
||||
swc->last_y=swc->phase=0;
|
||||
swc->last_dydt=1.0;
|
||||
} else {
|
||||
phase=swc->phase;
|
||||
i=0;
|
||||
amp=Min(I32_MAX,I32_MAX*_amp);
|
||||
f=2*ã/swc->sample_rate*_freq;
|
||||
switch (_waveform) {
|
||||
case WF_NOISE:
|
||||
a=2.0/ã*amp;
|
||||
break;
|
||||
case WF_SAWTOOTH:
|
||||
a=amp/ã;
|
||||
break;
|
||||
case WF_SINE:
|
||||
phase=SinPhaseCont(swc->last_y,swc->last_dydt,amp,0.0);
|
||||
break;
|
||||
}
|
||||
while (phase<0)
|
||||
phase+=2*ã;
|
||||
while (phase>=2*ã)
|
||||
phase-=2*ã;
|
||||
num_samples*=swc->channels;
|
||||
while (i<num_samples) {
|
||||
switch (_waveform) {
|
||||
case WF_SQUARE:
|
||||
if (phase>=ã)
|
||||
j=-amp;
|
||||
else
|
||||
j=amp;
|
||||
break;
|
||||
case WF_SINE:
|
||||
j=amp*Sin(phase);
|
||||
break;
|
||||
case WF_TRI:
|
||||
if (phase>=ã) {
|
||||
swc->last_y=swc->next_y;
|
||||
swc->next_y=-amp*Sign(swc->last_y)+.00001;
|
||||
phase-=ã;
|
||||
}
|
||||
j=(swc->last_y*(ã-phase)+swc->next_y*phase)/ã;
|
||||
break;
|
||||
case WF_SAWTOOTH:
|
||||
j=a*(phase-ã);
|
||||
break;
|
||||
case WF_NOISE:
|
||||
if (phase<ã) {
|
||||
if (phase<f) {
|
||||
swc->last_y=swc->next_y;
|
||||
swc->next_y=a*RandI16/U16_MAX;
|
||||
}
|
||||
j=swc->last_y*(ã-phase)+swc->next_y*phase;
|
||||
} else {
|
||||
if (phase-ã<f) {
|
||||
swc->last_y=swc->next_y;
|
||||
swc->next_y=a*RandI16/U16_MAX;
|
||||
}
|
||||
j=swc->last_y*(2.0*ã-phase)+swc->next_y*(phase-ã);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//left channel
|
||||
k=j*_left;
|
||||
if (swc->sample_bits==16) {
|
||||
k>>=16;
|
||||
buf(I16 *)[i++]+=k;
|
||||
} else {
|
||||
if (swc->sample_bits==24)
|
||||
k&=0xFFFFFF00;
|
||||
buf(I32 *)[i++]+=k;
|
||||
}
|
||||
//right channel
|
||||
if (swc->channels==2) {
|
||||
k=j*_right;
|
||||
if (swc->sample_bits==16) {
|
||||
k>>=16;
|
||||
buf(I16 *)[i++]+=k;
|
||||
} else {
|
||||
if (swc->sample_bits==24)
|
||||
k&=0xFFFFFF00;
|
||||
buf(I32 *)[i++]+=k;
|
||||
}
|
||||
}
|
||||
phase+=f;
|
||||
while (phase>=2*ã)
|
||||
phase-=2*ã;
|
||||
}
|
||||
if (_waveform==WF_SINE) {
|
||||
swc->last_y=amp*Sin(phase);
|
||||
swc->last_dydt=Cos(phase);
|
||||
}
|
||||
swc->phase=phase;
|
||||
}
|
||||
}
|
224
src/Home/Sound/HDAudio1/Sup1Snd/SndMusic.ZC
Normal file
224
src/Home/Sound/HDAudio1/Sup1Snd/SndMusic.ZC
Normal file
|
@ -0,0 +1,224 @@
|
|||
#help_index "Sound/Music"
|
||||
|
||||
public class CMusicGlbls
|
||||
{
|
||||
U8 *cur_song;
|
||||
CTask *cur_song_task;
|
||||
I64 octave;
|
||||
F64 note_len;
|
||||
U8 note_map[7];
|
||||
Bool mute;
|
||||
I64 meter_top,meter_bottom;
|
||||
F64 tempo,stacatto_factor;
|
||||
|
||||
//If you wish to sync with a
|
||||
//note in a Play() string. 0 is the start
|
||||
I64 play_note_num;
|
||||
|
||||
F64 tM_correction,last_Beat,last_tM;
|
||||
} music={NULL,NULL,4,1.0,{0,2,3,5,7,8,10},FALSE,4,4,2.5,0.9,0,0,0,0};
|
||||
|
||||
#help_index "Sound/Music;Time/Seconds"
|
||||
public F64 tM()
|
||||
{//Time in seconds synced to music subsystem.
|
||||
return (counts.jiffies+music.tM_correction)/JIFFY_FREQ;
|
||||
}
|
||||
|
||||
public F64 Beat()
|
||||
{//Time in music beats.
|
||||
F64 res,cur_tM;
|
||||
PUSHFD
|
||||
CLI
|
||||
if (mp_count>1)
|
||||
while (LBts(&sys_semas[SEMA_TMBEAT],0))
|
||||
PAUSE
|
||||
cur_tM=tM;
|
||||
res=music.last_Beat;
|
||||
if (music.tempo)
|
||||
res+=(cur_tM-music.last_tM)*music.tempo;
|
||||
music.last_tM=cur_tM;
|
||||
music.last_Beat=res;
|
||||
LBtr(&sys_semas[SEMA_TMBEAT],0);
|
||||
POPFD
|
||||
return res;
|
||||
}
|
||||
|
||||
#help_index "Sound/Music"
|
||||
U8 *MusicSetOctave(U8 *st)
|
||||
{
|
||||
I64 ch;
|
||||
ch=*st++;
|
||||
while ('0'<=ch<='9') {
|
||||
music.octave=ch-'0';
|
||||
ch=*st++;
|
||||
}
|
||||
return --st;
|
||||
}
|
||||
|
||||
U8 *MusicSetMeter(U8 *st)
|
||||
{
|
||||
I64 ch;
|
||||
ch=*st++;
|
||||
while (ch=='M') {
|
||||
ch=*st++;
|
||||
if ('0'<=ch<='9') {
|
||||
music.meter_top=ch-'0';
|
||||
ch=*st++;
|
||||
}
|
||||
if (ch=='/')
|
||||
ch=*st++;
|
||||
if ('0'<=ch<='9') {
|
||||
music.meter_bottom=ch-'0';
|
||||
ch=*st++;
|
||||
}
|
||||
}
|
||||
return --st;
|
||||
}
|
||||
|
||||
U8 *MusicSetNoteLen(U8 *st)
|
||||
{
|
||||
Bool cont=TRUE;
|
||||
do {
|
||||
switch (*st++) {
|
||||
case 'w': music.note_len=4.0; break;
|
||||
case 'h': music.note_len=2.0; break;
|
||||
case 'q': music.note_len=1.0; break;
|
||||
case 'e': music.note_len=0.5; break;
|
||||
case 's': music.note_len=0.25; break;
|
||||
case 't': music.note_len=2.0*music.note_len/3.0; break;
|
||||
case '.': music.note_len=1.5*music.note_len; break;
|
||||
default:
|
||||
st--;
|
||||
cont=FALSE;
|
||||
}
|
||||
} while (cont);
|
||||
return st;
|
||||
}
|
||||
|
||||
public U0 Play(U8 *st,U8 *words=NULL)
|
||||
{/* Notes are entered with a capital letter.
|
||||
|
||||
Octaves are entered with a digit and
|
||||
stay set until changed. Mid C is octave 4.
|
||||
|
||||
Durations are entered with
|
||||
'w' whole note
|
||||
'h' half note
|
||||
'q' quarter note
|
||||
'e' eighth note
|
||||
't' sets to 2/3rds the current duration
|
||||
'.' sets to 1.5 times the current duration
|
||||
durations stay set until changed.
|
||||
|
||||
'(' tie, placed before the note to be extended
|
||||
|
||||
$LK,"music.meter_top",A="MN:CMusicGlbls"$,$LK,"music.meter_bottom",A="MN:CMusicGlbls"$ is set with
|
||||
"M3/4"
|
||||
"M4/4"
|
||||
etc.
|
||||
|
||||
Sharp and flat are done with '#' or 'b'.
|
||||
|
||||
The var music.stacatto_factor can
|
||||
be set to a range from 0.0 to 1.0.
|
||||
|
||||
The var music.tempo is quarter-notes
|
||||
per second.It defaults to
|
||||
2.5 and gets faster when bigger.
|
||||
*/
|
||||
U8 *word,*last_st;
|
||||
I64 note,octave,i=0,ona,timeout_val,timeout_val2;
|
||||
Bool tie;
|
||||
F64 d,on_jiffies,off_jiffies;
|
||||
music.play_note_num=0;
|
||||
while (*st) {
|
||||
timeout_val=counts.jiffies;
|
||||
tie=FALSE;
|
||||
|
||||
do {
|
||||
last_st=st;
|
||||
if (*st=='(') {
|
||||
tie=TRUE;
|
||||
st++;
|
||||
} else {
|
||||
st=MusicSetMeter(st);
|
||||
st=MusicSetOctave(st);
|
||||
st=MusicSetNoteLen(st);
|
||||
}
|
||||
} while (st!=last_st);
|
||||
|
||||
if (!*st) break;
|
||||
note=*st++-'A';
|
||||
if (note<7) {
|
||||
note=music.note_map[note];
|
||||
octave=music.octave;
|
||||
if (*st=='b') {
|
||||
note--;
|
||||
if (note==2)
|
||||
octave--;
|
||||
st++;
|
||||
} else if (*st=='#') {
|
||||
note++;
|
||||
if (note==3)
|
||||
octave++;
|
||||
st++;
|
||||
}
|
||||
ona=Note2Ona(note,octave);
|
||||
} else
|
||||
ona=0;
|
||||
if (words && (word=ListSub(i++,words)) && StrCompare(word,""))
|
||||
"%s",word;
|
||||
d=JIFFY_FREQ*music.note_len/music.tempo;
|
||||
if (tie) {
|
||||
on_jiffies =d;
|
||||
off_jiffies =0;
|
||||
} else {
|
||||
on_jiffies =d*music.stacatto_factor;
|
||||
off_jiffies =d*(1.0-music.stacatto_factor);
|
||||
}
|
||||
timeout_val+=on_jiffies;
|
||||
timeout_val2=timeout_val+off_jiffies;
|
||||
|
||||
if (!music.mute)
|
||||
Sound(ona);
|
||||
SleepUntil(timeout_val);
|
||||
music.tM_correction+=on_jiffies-ToI64(on_jiffies);
|
||||
|
||||
if (!music.mute)
|
||||
Sound;
|
||||
SleepUntil(timeout_val2);
|
||||
music.tM_correction+=off_jiffies-ToI64(off_jiffies);
|
||||
|
||||
music.play_note_num++;
|
||||
}
|
||||
}
|
||||
|
||||
U0 MusicSettingsReset()
|
||||
{
|
||||
music.play_note_num=0;
|
||||
music.stacatto_factor=0.9;
|
||||
music.tempo=2.5;
|
||||
music.octave=4;
|
||||
music.note_len=1.0;
|
||||
music.meter_top=4;
|
||||
music.meter_bottom=4;
|
||||
SoundReset;
|
||||
PUSHFD
|
||||
CLI
|
||||
if (mp_count>1)
|
||||
while (LBts(&sys_semas[SEMA_TMBEAT],0))
|
||||
PAUSE
|
||||
music.last_tM=tM;
|
||||
music.last_Beat=0.0;
|
||||
LBtr(&sys_semas[SEMA_TMBEAT],0);
|
||||
POPFD
|
||||
}
|
||||
|
||||
MusicSettingsReset;
|
||||
|
||||
U0 CurSongTask()
|
||||
{
|
||||
Fs->task_end_cb=&SoundTaskEndCB;
|
||||
while (TRUE)
|
||||
Play(music.cur_song);
|
||||
}
|
|
@ -2663,12 +2663,25 @@ class CSMBIOSBatteryInfo
|
|||
#define PCIR_MIN_GRANT 0x3E
|
||||
#define PCIR_MAX_LATENCY 0x3F
|
||||
|
||||
// PCI Command Register bit flags
|
||||
#define PCI_CMDf_IOEN 0 // I/O Space Enable
|
||||
#define PCI_CMDf_MSEN 1 // Memory Space Enable
|
||||
#define PCI_CMDf_BMEN 2 // Bus Master Enable
|
||||
#define PCI_CMDf_INTD 10 // Interrupt Disable
|
||||
|
||||
#define PCI_CMDF_IOEN (1 << PCI_CMDf_IOEN)
|
||||
#define PCI_CMDF_MSEN (1 << PCI_CMDf_MSEN)
|
||||
#define PCI_CMDF_BMEN (1 << PCI_CMDf_BMEN)
|
||||
#define PCI_CMDF_INTD (1 << PCI_CMDf_INTD)
|
||||
|
||||
//PCI class codes
|
||||
#define PCIC_STORAGE 0x1
|
||||
#define PCIC_NETWORK 0x2
|
||||
#define PCIC_MULTIMEDIA 0x4
|
||||
|
||||
//PCI subclass codes
|
||||
#define PCISC_ETHERNET 0x0
|
||||
#define PCISC_AUDIO 0x3
|
||||
#define PCISC_AHCI 0x6
|
||||
|
||||
//PCI I/O ports
|
||||
|
|
|
@ -69,14 +69,14 @@ U0 PCIWriteU32(I64 bus, I64 dev, I64 fun, I64 rg, I64 val)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
U0 PCIWriteU8(I64 bus, I64 dev, I64 fun, I64 rg, I64 val)
|
||||
{//Write U8 in PCI configspace at bus, dev, fun, reg.
|
||||
if (sys_pci_services)
|
||||
PCIBIOSWriteU8(bus, dev, fun, rg, val);
|
||||
else
|
||||
{
|
||||
PCIWriteU32(bus, dev, fun, rg, val & 0xFF);
|
||||
val = PCIReadU32(bus, dev, fun, rg) & ~0xFF | val & 0xFF;
|
||||
PCIWriteU32(bus, dev, fun, rg, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,8 @@ U0 PCIWriteU16(I64 bus, I64 dev, I64 fun, I64 rg, I64 val)
|
|||
PCIBIOSWriteU16(bus, dev, fun, rg, val);
|
||||
else
|
||||
{
|
||||
PCIWriteU32(bus, dev, fun, rg, val & 0xFFFF);
|
||||
val = PCIReadU32(bus, dev, fun, rg) & ~0xFFFF | val & 0xFFFF;
|
||||
PCIWriteU32(bus, dev, fun, rg, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,43 +1,40 @@
|
|||
# Nuke built-in rules and variables.
|
||||
override MAKEFLAGS += -rR
|
||||
MAKEFLAGS += -rR
|
||||
.SUFFIXES:
|
||||
|
||||
# This is the name that our final executable will have.
|
||||
# Change as needed.
|
||||
override OUTPUT := kernel
|
||||
|
||||
# Convenience macro to reliably declare user overridable variables.
|
||||
define DEFAULT_VAR =
|
||||
ifeq ($(origin $1),default)
|
||||
override $(1) := $(2)
|
||||
endif
|
||||
ifeq ($(origin $1),undefined)
|
||||
override $(1) := $(2)
|
||||
endif
|
||||
endef
|
||||
override USER_VARIABLE = $(if $(filter $(origin $(1)),default undefined),$(eval override $(1) := $(2)))
|
||||
|
||||
# User controllable C compiler command.
|
||||
override DEFAULT_KCC := cc
|
||||
$(eval $(call DEFAULT_VAR,KCC,$(DEFAULT_KCC)))
|
||||
$(call USER_VARIABLE,KCC,cc)
|
||||
|
||||
# User controllable linker command.
|
||||
override DEFAULT_KLD := ld
|
||||
$(eval $(call DEFAULT_VAR,KLD,$(DEFAULT_KLD)))
|
||||
$(call USER_VARIABLE,KLD,ld)
|
||||
|
||||
# User controllable C flags.
|
||||
override DEFAULT_KCFLAGS := -g -O2 -pipe
|
||||
$(eval $(call DEFAULT_VAR,KCFLAGS,$(DEFAULT_KCFLAGS)))
|
||||
$(call USER_VARIABLE,KCFLAGS,-g -O2 -pipe)
|
||||
|
||||
# User controllable C preprocessor flags. We set none by default.
|
||||
override DEFAULT_KCPPFLAGS :=
|
||||
$(eval $(call DEFAULT_VAR,KCPPFLAGS,$(DEFAULT_KCPPFLAGS)))
|
||||
$(call USER_VARIABLE,KCPPFLAGS,)
|
||||
|
||||
# User controllable nasm flags.
|
||||
override DEFAULT_KNASMFLAGS := -F dwarf -g
|
||||
$(eval $(call DEFAULT_VAR,KNASMFLAGS,$(DEFAULT_KNASMFLAGS)))
|
||||
$(call USER_VARIABLE,KNASMFLAGS,-F dwarf -g)
|
||||
|
||||
# User controllable linker flags. We set none by default.
|
||||
override DEFAULT_KLDFLAGS :=
|
||||
$(eval $(call DEFAULT_VAR,KLDFLAGS,$(DEFAULT_KLDFLAGS)))
|
||||
$(call USER_VARIABLE,KLDFLAGS,)
|
||||
|
||||
# Check if KCC is Clang.
|
||||
override KCC_IS_CLANG := $(shell ! $(KCC) --version 2>/dev/null | grep 'clang' >/dev/null 2>&1; echo $$?)
|
||||
|
||||
# If the C compiler is Clang, set the target as needed.
|
||||
ifeq ($(KCC_IS_CLANG),1)
|
||||
override KCC += \
|
||||
-target x86_64-unknown-none
|
||||
endif
|
||||
|
||||
# Internal C flags that should not be changed by the user.
|
||||
override KCFLAGS += \
|
||||
|
|
|
@ -9,9 +9,10 @@ ENTRY(kmain)
|
|||
/* process. */
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
requests PT_LOAD;
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
|
@ -22,6 +23,16 @@ SECTIONS
|
|||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
.requests : {
|
||||
KEEP(*(.requests_start_marker))
|
||||
KEEP(*(.requests))
|
||||
KEEP(*(.requests_end_marker))
|
||||
} :requests
|
||||
|
||||
/* Move to the next memory page for .text */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
@ -38,12 +49,6 @@ SECTIONS
|
|||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
|
||||
/* Place the sections that contain the Limine requests as part of the .data */
|
||||
/* output section. */
|
||||
KEEP(*(.requests_start_marker))
|
||||
KEEP(*(.requests))
|
||||
KEEP(*(.requests_end_marker))
|
||||
} :data
|
||||
|
||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||
|
|
Loading…
Reference in a new issue