#include #include #include #include #include #include #include #include #include "gip.h" #define READ_WAV_FILE 1 // UIO & pointers int fdMmvs = open("/dev/uio0", O_RDWR); int fdMem = open("/dev/uio16", O_RDWR); static PGIP_AXI_2D_MM2VS mmvs = (PGIP_AXI_2D_MM2VS)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fdMmvs, 0); // open sound file int fdSoundFile = open("/home/user/Music/HaveANiceDay.wav", O_RDONLY); // Funktion zum fuellen des Buffers mit einer Sinus-Funktion mit fester Periodendauer // bufferSize: Groesse des Buffers in Bytes void fillBuffer(int16_t* pBuffer, uint32_t bufferSize); // Funktion zum fuellen des Buffers mit einer Sinus-Funktion mit variabler Periodendauer // bufferSize: Groesse des Buffers in Bytes // period: Anzahl der Abtastwerte pro eine Periode void fillBufferSine(int16_t *pBuffer, uint32_t bufferSize, uint32_t period); void fillBufferSoundFile(int fd, int16_t *pBuffer, uint32_t bufferSize); // Hinweis zu "__attribute__((unused))" // Hiermit wird dem Compiler mitgeteilt, dass eine Variable oder eine Funktion eventuell nicht verwendet wird // Damit wird keine "Unused-Warnung" für diese Variable oder Funktion ausgegeben // Die hier mit diesem Attribut gekennzeichneten Variablen werden in der aktuellen Version des Codes nicht verwendet // Wenn der Milestone abgeschlossen ist, werden sie dagegen sehr wohl Verwendung finden __attribute__((unused)) static uint8_t* pMem = (uint8_t*)mmap(NULL, 0x20000000, PROT_READ | PROT_WRITE, MAP_SHARED, fdMem, 0); void MM2VS_Handler() { __attribute__((unused)) uint32_t uio16PhysBase = 0x30000000; // UIO16 physical Baseaddress uint32_t bufferStart = 0x38000000; // Start of Audiobuffers uint32_t bufferStartOffset = bufferStart - uio16PhysBase; uint32_t bufferChunkSize = 1024; uint32_t bufferNumChunks = 188; __attribute__((unused)) int16_t* pBuffer; // WAV-Datei Header einlesen und verwerfen uint8_t buf[44]; read(fdSoundFile, buf, 44); // MM2VS Initialization mmvs->VS2MM_Control &= ~1; // VS2MM: Run-Bit loeschen mmvs->MM2VS_Control &= ~1; // MM2VS: Run-Bit loeschen usleep(500000); // 500 ms warten. Falls das MMVS-IP noch aktiv war, kann es so noch ausstehende Speicherzugriffe beenden mmvs->MM2VS_HorizontalBytes = bufferChunkSize; mmvs->MM2VS_Stride = bufferChunkSize; mmvs->MM2VS_StartAddress = bufferStart; mmvs->MM2VS_VerticalLines = bufferNumChunks; mmvs->MM2VS_InterruptLine = bufferNumChunks - 1; mmvs->InterruptEnable = 0; // IP-INT-Enable zuruecksetzen mmvs->InterruptStatus = 0; // IP-INT-Status zuruecksetzen // Enable Interrupts mmvs->InterruptEnable = 0x1; int reenable = 1; write(fdMmvs, (void*) &reenable, 4); // Run MM2VS mmvs->MM2VS_Control |= 0x1; while (1) { // Reenable Interrupts // Bitte beachten: // Wir verwenden pegel-sensitive Interrupts. // Das bedeutet, dass VOR der erneuten Freigabe der Interrupts (= reenable) // der Interrupt-Status im IP zurueckgesetzt werden muss - und NICHT DANACH // Falls Ihnen nicht klar ist, warum das so ist, fragen Sie nach! int pending; int reenable = 1; read(fdMmvs, (void*) &pending, 4); mmvs->InterruptStatus = 0; write(fdMmvs, (void*) &reenable, 4); // Fill currrently unused buffer volatile uint32_t lastFrameAddress = mmvs->MM2VS_LastFrameAddress; printf("LastFrameAddress: 0x%x\n", (unsigned int) lastFrameAddress); if ((void *) lastFrameAddress == NULL) { pBuffer = (int16_t *) ((uint32_t) pMem + bufferStartOffset); } else if (lastFrameAddress == bufferStart) { pBuffer = (int16_t *) ((uint32_t) pMem + bufferStartOffset + bufferChunkSize * bufferNumChunks); } else { pBuffer = (int16_t *) ((uint32_t) pMem + bufferStartOffset); } printf("Fill DataAddress: 0x%x\n", (unsigned int) pBuffer); // Fill not used buffer with values // fillBuffer(pBuffer, bufferChunkSize*bufferNumChunks); //fillBufferSine(pBuffer, bufferChunkSize*bufferNumChunks, 12); int ret = read(fdSoundFile, pBuffer, bufferChunkSize*bufferNumChunks); printf("Bytes read: %u", ret); if (ret == -1) { printf("Failed to read Soundfile\n"); } } } int main(int argc, char** argv) { printf("Start Program\n"); if (fdSoundFile == -1) { printf("Fehler beim Einlesen der WAV-Datei."); return 1; } std::thread t1(MM2VS_Handler); t1.join(); return 0; } void fillBuffer(int16_t* pBuffer, uint32_t bufferSize) { // Sinuswerte einer Periode auf 8 mal 16bit aufgeteilt int16_t sine_values[] = {0,23169,32767,23169,0,-23170,-32768,-23170}; for (uint32_t i = 0; i < bufferSize/2; i++) { int16_t *pData = pBuffer + i; *pData = sine_values[i%8]; } } void fillBufferSine(int16_t *pBuffer, uint32_t bufferSize, uint32_t period) { static uint32_t n = 0; double deltaX = 2 * M_PI / period; for (uint32_t i = 0; i < bufferSize/2; i++) { int16_t *pData = pBuffer + i; int16_t sineValue = (int16_t) 32767 * sin(n*deltaX); *pData = sineValue; n = (n+1) % period; } } void fillBufferSoundFile(int fd, int16_t *pBuffer, uint32_t bufferSize) { read(fdSoundFile, pBuffer, bufferSize); }