156 lines
5.2 KiB
C++
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);
|
|
}
|