Files
Matthias Biermann 25d5d0fd17 M5: Abgeschlossen
2024-12-05 10:22:08 +01:00

156 lines
5.2 KiB
C++

#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <thread>
#include <stdio.h>
#include <math.h>
#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);
}