simplify dma writting

This commit is contained in:
F5OEO 2019-01-06 10:51:52 +00:00
parent d23e1fd8fc
commit 326d51cbbc
12 changed files with 469 additions and 740 deletions

View file

@ -4,7 +4,7 @@ LDFLAGS = -lm -lrt -lpthread
CCP = c++
CC = cc
librpitx: librpitx.h gpio.h gpio.cpp dma.h dma.cpp mailbox.c raspberry_pi_revision.c fmdmasync.h fmdmasync.cpp ngfmdmasync.h ngfmdmasync.cpp dsp.h dsp.cpp iqdmasync.h iqdmasync.cpp serialdmasync.h serialdmasync.cpp phasedmasync.h phasedmasync.cpp fskburst.h fskburst.cpp ookburst.cpp ookburst.h atv.h atv.cpp
librpitx: librpitx.h gpio.h gpio.cpp dma.h dma.cpp mailbox.c raspberry_pi_revision.c fmdmasync.h fmdmasync.cpp ngfmdmasync.h ngfmdmasync.cpp dsp.h dsp.cpp iqdmasync.h iqdmasync.cpp serialdmasync.h serialdmasync.cpp phasedmasync.h phasedmasync.cpp fskburst.h fskburst.cpp ookburst.cpp ookburst.h atv.h atv.cpp util.h
$(CC) $(CFLAGS) -c -o mailbox.o mailbox.c
$(CC) $(CFLAGS) -c -o raspberry_pi_revision.o raspberry_pi_revision.c
$(CCP) $(CXXFLAGS) -c dsp.cpp iqdmasync.cpp ngfmdmasync.cpp fmdmasync.cpp dma.cpp gpio.cpp serialdmasync.cpp phasedmasync.cpp amdmasync.h amdmasync.cpp fskburst.cpp ookburst.cpp atv.cpp

View file

@ -72,39 +72,17 @@ void amdmasync::SetDmaAlgo()
//@0
//Set Amplitude by writing to PADS
cbp->info = 0;//BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
cbp->dst = 0x7E000000+(PADS_GPIO_0<<2)+PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
SetEasyCB(cbp,samplecnt*registerbysample,dma_pad,1);
cbp++;
//@1
//Set Amplitude to FSEL for amplitude=0
cbp->info = 0;//BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample+1]);
cbp->dst = 0x7E000000 + (GPFSEL0<<2)+GENERAL_BASE;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
SetEasyCB(cbp,samplecnt*registerbysample+1,dma_fsel,1);
cbp++;
// Delay
if(syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if(syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A<<2) + PCM_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
SetEasyCB(cbp,samplecnt*registerbysample,syncwithpwm?dma_pwm:dma_pcm,1);
cbp++;
}

View file

@ -77,6 +77,10 @@ void atv::SetDmaAlgo()
uint32_t level1 = mem_virt_to_phys(&usermem[(usermemsize - 2)]);
uint32_t level4 = mem_virt_to_phys(&usermem[(usermemsize - 3)]);
uint32_t index_level0 = usermemsize - 1;
uint32_t index_level1 = usermemsize - 2;
uint32_t index_level4 = usermemsize - 3;
int shortsync_0 = 2;
int shortsync_1 = 30;
@ -96,267 +100,60 @@ void atv::SetDmaAlgo()
//2us 0,30us 1
//@0
//SYNC preegalisation 2us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level0; //Amp 0
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * shortsync_0; //2us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level0, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, shortsync_0);
//SYNC preegalisation 30us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level1; //Amp 1
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * shortsync_1; //30us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level1, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, shortsync_1);
}
//SYNC top trame 5*4*2frameCB
for (int i = 0; i < 5; i++)
{
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level0; //Amp 0 27us
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level0, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, longsync_0);
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * longsync_0; //27us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level1; //Amp 1 5us
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * longsync_1; //5us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level1, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, longsync_1);
}
//postegalisation ; copy paste from preegalisation
//5*4*2CB
for (int i = 0; i < 5 /*-i*/; i++)
for (int i = 0; i < 5 + frame; i++)
{
//2us 0,30us 1
//@0
//SYNC preegalisation 2us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level0; //Amp 0
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * shortsync_0; //2us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level0, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, shortsync_0);
//SYNC preegalisation 30us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level1; //Amp 1
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * shortsync_1; //30us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level1, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, shortsync_1);
}
//(304+305)*(4+52*2+2)CB
for (int line = 0; line < 305 /* 317 + frame*/; line++)
{
//@0
//SYNC 0/ 5us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level0; //Amp 0
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level0, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, normalsync_0);
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * normalsync_0; //4us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@0
//SYNC 1/ 5us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level1; //Amp 1
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * normalsync_1; //5us;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level1, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, normalsync_1);
for (uint32_t samplecnt = 0; samplecnt < 52; samplecnt++) //52 us
{
//sampletab[samplecnt * registerbysample] = (0x5A << 24) + (3 & 0x7) + (1 << 4) + (0 << 3); // Amplitude PAD
//@0
//DATA IN / 1us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
//if(line<20) cbp->src=level1;
//if((line>=20)&&(line<40)) cbp->src=level4;
//if(line>=20)
cbp->src = mem_virt_to_phys(&usermem[samplecnt + line * 52 + frame * 312 * 52]);
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4; //1us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, samplecnt + line * 52 + frame * 312 * 52, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, 1);
}
//FRONT PORSH
//SYNC 2us
cbp->info = 0; //BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = level1; //Amp 1
cbp->dst = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
// Delay
if (syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if (syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE;
cbp->length = 4 * frontsync_1; //2us
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++, index_level1, dma_pad, 1);
SetEasyCB(cbp++, 0, syncwithpwm ? dma_pwm : dma_pcm, frontsync_1);
}
}
cbp--;
@ -371,22 +168,11 @@ void atv::SetFrame(unsigned char *Luminance, size_t Lines)
for (size_t x = 0; x < 52; x++)
{
int AmplitudePAD = (Luminance[i * 52 + x] / 255.0) * 6.0 + 1; //1 to 7
// usermem[i* 52 + x] = (0x5A << 24) + (AmplitudePAD & 0x7) + (1 << 4) + (0 << 3); // Amplitude PAD
if (i % 2 == 0) // First field
usermem[i * 52 / 2 + x] = (0x5A << 24) + (AmplitudePAD & 0x7) + (1 << 4) + (0 << 3); // Amplitude PAD
else
usermem[(i - 1) * 52 / 2 + x + 52 * 312] = (0x5A << 24) + (AmplitudePAD & 0x7) + (1 << 4) + (0 << 3); // Amplitude PAD
}
/*for (size_t x = 0; x < 52; x++)
{
int AmplitudePAD = (Luminance[i * 52 + x]/255.0) * 6 + 1; //1 to 7
if (i % 2 == 0) // First field
usermem[i * 52 / 2 + x] = (0x5A << 24) + (AmplitudePAD & 0x7) + (1 << 4) + (0 << 3); // Amplitude PAD
else //second field
usermem[i * 52 / 2 + Lines / 2 + x] = (0x5A << 24) + (AmplitudePAD & 0x7) + (1 << 4) + (0 << 3); // Amplitude PAD
}
*/
}
}
}

View file

@ -18,6 +18,7 @@ This program is free software: you can redistribute it and/or modify
#include "dma.h"
#include "stdio.h"
#include "util.h"
extern "C"
{
@ -166,6 +167,33 @@ bool dma::isunderflow()
return ((dma_reg.gpioreg[DMA_CS+channel*0x40]&DMA_CS_INT)>0);
}
bool dma::SetCB(dma_cb_t *cbp,uint32_t dma_flag,uint32_t src,uint32_t dst,uint32_t repeat)
{
cbp->info = dma_flag;
cbp->src = src;
cbp->dst = dst;
cbp->length = 4*repeat;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
return true;
}
bool dma::SetEasyCB(dma_cb_t *cbp,uint32_t index,dma_common_reg dst,uint32_t repeat)
{
uint32_t flag=BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP;
uint32_t src=mem_virt_to_phys(&usermem[index]);
switch(dst)
{
case dma_pllc_frac :break;
case dma_fsel:break;
case dma_pad:break;
case dma_pwm : flag|=BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);break;
case dma_pcm : flag|=BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);break;
}
SetCB(cbp,flag,src,dst,repeat);
return true;
}
//**************************************** BUFFER DMA ********************************************************
bufferdma::bufferdma(int Channel,uint32_t tbuffersize,uint32_t tcbbysample,uint32_t tregisterbysample):dma(Channel,tbuffersize*tcbbysample,tbuffersize*tregisterbysample)
{

View file

@ -1,8 +1,9 @@
#ifndef DEF_DMA
#define DEF_DMA
#include "stdint.h"
#include "gpio.h"
#include "util.h"
// ---- Memory allocating defines
// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
#define MEM_FLAG_DISCARDABLE (1 << 0) /* can be resized to 0 at any time. Use for cached data */
@ -20,7 +21,6 @@
#define BCM2708_DMA_NO_WIDE_BURSTS (1 << 26)
#define BCM2708_DMA_WAIT_RESP (1 << 3)
#define BCM2708_DMA_D_DREQ (1 << 6)
#define BCM2708_DMA_PER_MAP(x) ((x) << 16)
#define BCM2708_DMA_END (1 << 1)
@ -41,23 +41,25 @@
#define DREQ_SPI_SLAVE_TX 8
#define DREQ_SPI_SLAVE_RX 9
class dma
{
protected:
struct {
struct
{
int handle; /* From mbox_open() */
unsigned mem_ref; /* From mem_alloc() */
unsigned bus_addr; /* From mem_lock() */
uint8_t *virt_addr; /* From mapmem() */
} mbox;
typedef struct {
typedef struct
{
uint32_t info, src, dst, length,
stride, next, pad[2];
} dma_cb_t; //8*4=32 bytes
typedef struct {
typedef struct
{
uint8_t *virtaddr;
uint32_t physaddr;
} page_map_t;
@ -72,7 +74,6 @@ class dma
uint32_t mem_flag; //Cache or not depending on Rpi1 or 2/3
uint32_t dram_phys_base;
public:
dma_cb_t *cbarray;
uint32_t cbsize;
@ -90,16 +91,13 @@ class dma
int getcbposition();
bool isrunning();
bool isunderflow();
bool SetCB(dma_cb_t *cbp, uint32_t dma_flag, uint32_t src, uint32_t dst, uint32_t repeat);
bool SetEasyCB(dma_cb_t *cbp, uint32_t index, dma_common_reg dst, uint32_t repeat);
};
#define PHYSICAL_BUS 0x7E000000
class bufferdma : public dma
{
protected:
uint32_t current_sample;
uint32_t last_sample;
uint32_t sample_available;
@ -116,6 +114,5 @@ class bufferdma:public dma
int GetBufferAvailable();
int GetUserMemIndex();
int PushSample(int Index);
};
#endif

View file

@ -3,7 +3,7 @@
#include "stdint.h"
#include <cstdio>
#define PHYSICAL_BUS 0x7E000000
class gpio
{
@ -16,7 +16,6 @@ class gpio
uint32_t GetPeripheralBase();
};
#define DMA_BASE (0x00007000)
#define DMA_LEN 0xF00
@ -53,8 +52,6 @@ class dmagpio:public gpio
public:
dmagpio();
};
//************************************ GENERAL GPIO ***************************************
@ -69,7 +66,17 @@ class dmagpio:public gpio
#define GPPUDCLK0 (0x98 / 4)
#define GPPUDCLK1 (0x9C / 4)
enum {fsel_input,fsel_output,fsel_alt5,fsel_alt4,fsel_alt0,fsel_alt1,fsel_alt2,fsel_alt3};
enum
{
fsel_input,
fsel_output,
fsel_alt5,
fsel_alt4,
fsel_alt0,
fsel_alt1,
fsel_alt2,
fsel_alt3
};
class generalgpio : public gpio
{
@ -170,7 +177,6 @@ class generalgpio:public gpio
#define CM_EMMCCTL 0x1c0
#define CM_EMMCDIV 0x1c4
#define CM_LOCK (0x114 / 4)
#define CM_LOCK_FLOCKH (1 << 12)
#define CM_LOCK_FLOCKD (1 << 11)
@ -195,8 +201,6 @@ class generalgpio:public gpio
#define CM_PLLH (0x110 / 4)
#define CM_PLLB (0x170 / 4)
#define A2W_PLLA_ANA0 (0x1010 / 4)
#define A2W_PLLC_ANA0 (0x1030 / 4)
#define A2W_PLLD_ANA0 (0x1050 / 4)
@ -245,7 +249,17 @@ class generalgpio:public gpio
#define XOSC_FREQUENCY 19200000
//Parent PLL
enum {clk_gnd,clk_osc,clk_debug0,clk_debug1,clk_plla,clk_pllc,clk_plld,clk_hdmi};
enum
{
clk_gnd,
clk_osc,
clk_debug0,
clk_debug1,
clk_plla,
clk_pllc,
clk_plld,
clk_hdmi
};
class clkgpio : public gpio
{
@ -257,6 +271,7 @@ class clkgpio:public gpio
uint64_t CentralFrequency = 0;
generalgpio gengpio;
double clk_ppm = 0;
public:
int PllFixDivider = 8; //Fix divider from the master clock in advanced mode
@ -280,12 +295,8 @@ class clkgpio:public gpio
void Setppm(double ppm);
void SetppmFromNTP();
void SetPLLMasterLoop(int Ki, int Kp, int Ka);
};
//************************************ PWM GPIO ***************************************
#define PWM_BASE (0x0020C000)
@ -300,7 +311,6 @@ class clkgpio:public gpio
#define PWMCLK_CNTL (40) // Clk register
#define PWMCLK_DIV (41) // Clk register
#define PWMCTL_MSEN2 (1 << 15)
#define PWMCTL_USEF2 (1 << 13)
#define PWMCTL_RPTL2 (1 << 10)
@ -316,7 +326,12 @@ class clkgpio:public gpio
#define PWMCTL_PWEN1 (1 << 0)
#define PWMDMAC_ENAB (1 << 31)
#define PWMDMAC_THRSHLD ((15 << 8) | (15 << 0))
enum pwmmode{pwm1pin,pwm2pin,pwm1pinrepeat};
enum pwmmode
{
pwm1pin,
pwm2pin,
pwm1pinrepeat
};
class pwmgpio : public gpio
{
@ -329,6 +344,7 @@ class pwmgpio:public gpio
bool ModulateFromMasterPLL = false;
int ModePwm = pwm1pin;
generalgpio gengpio;
public:
pwmgpio();
~pwmgpio();
@ -376,7 +392,6 @@ class pcmgpio:public gpio
uint64_t GetPllFrequency(int PllNo);
int SetFrequency(uint64_t Frequency);
int ComputePrediv(uint64_t Frequency);
};
//******************************* PAD GPIO (Amplitude) ***********************************
@ -396,4 +411,13 @@ class padgpio:public gpio
int setlevel(int level);
};
enum dma_common_reg
{
dma_pllc_frac = 0x7E000000 + (PLLC_FRAC << 2) + CLK_BASE,
dma_pwm = 0x7E000000 + (PWM_FIFO << 2) + PWM_BASE,
dma_pcm = 0x7E000000 + (PCM_FIFO_A << 2) + PCM_BASE,
dma_fsel = 0x7E000000 + (GPFSEL0 << 2) + GENERAL_BASE,
dma_pad = 0x7E000000 + (PADS_GPIO_0 << 2) + PADS_GPIO
};
#endif

View file

@ -81,55 +81,20 @@ void iqdmasync::SetDmaAlgo()
for (uint32_t samplecnt = 0; samplecnt < buffersize; samplecnt++)
{
//@0
//Set Amplitude by writing to PADS
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample+1]);
cbp->dst = 0x7E000000+(PADS_GPIO_0<<2)+PADS_GPIO;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
SetEasyCB(cbp,samplecnt*registerbysample+1,dma_pad,1);
cbp++;
//@2 Write a frequency sample : Order of DMA CS influence maximum rate : here 0,2,1 is the best : why !!!!!!
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
cbp->dst = 0x7E000000 + (PLLC_FRAC<<2) + CLK_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
SetEasyCB(cbp,samplecnt*registerbysample,dma_pllc_frac,1);
cbp++;
//@1
//Set Amplitude to FSEL for amplitude=0
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample+2]);
cbp->dst = 0x7E000000 + (GPFSEL0<<2)+GENERAL_BASE;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
SetEasyCB(cbp,samplecnt*registerbysample+2,dma_fsel,1);
cbp++;
//@3 Delay
if(syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info =BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(&usermem[(samplecnt+1)*registerbysample]);//mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if(syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A<<2) + PCM_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
SetEasyCB(cbp,samplecnt*registerbysample,syncwithpwm?dma_pwm:dma_pcm,1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
cbp++;

View file

@ -74,31 +74,12 @@ void ngfmdmasync::SetDmaAlgo()
// Write a frequency sample
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
cbp->dst = 0x7E000000 + (PLLC_FRAC<<2) + CLK_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
SetEasyCB(cbp,samplecnt*registerbysample,dma_pllc_frac,1);
cbp++;
// Delay
if(syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if(syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A<<2) + PCM_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
SetEasyCB(cbp,samplecnt*registerbysample,syncwithpwm?dma_pwm:dma_pcm,1);
cbp++;
}
@ -119,7 +100,7 @@ void ngfmdmasync::SetFrequencySample(uint32_t Index,float Frequency)
void ngfmdmasync::SetFrequencySamples(float *sample,size_t Size)
{
size_t NbWritten=0;
int OSGranularity=100;
int OSGranularity=200;
long int start_time;
long time_difference=0;
@ -133,19 +114,20 @@ void ngfmdmasync::SetFrequencySamples(float *sample,size_t Size)
int TimeToSleep=1e6*((int)buffersize*3/4-Available)/SampleRate-OSGranularity; // Sleep for theorically fill 3/4 of Fifo
if(TimeToSleep>0)
{
//fprintf(stderr,"buffer size %d Available %d SampleRate %d Sleep %d\n",buffersize,Available,SampleRate,TimeToSleep);
fprintf(stderr,"buffer size %d Available %d SampleRate %d Sleep %d\n",buffersize,Available,SampleRate,TimeToSleep);
usleep(TimeToSleep);
}
else
{
//fprintf(stderr,"No Sleep %d\n",TimeToSleep);
fprintf(stderr,"No Sleep %d\n",TimeToSleep);
sched_yield();
}
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
//fprintf(stderr,"Measure samplerate=%d\n",(int)((GetBufferAvailable()-Available)*1e9/time_difference));
Available=GetBufferAvailable();
int NewAvailable=GetBufferAvailable();
fprintf(stderr,"Newavailable %d Measure samplerate=%d\n",NewAvailable,(int)((GetBufferAvailable()-Available)*1e9/time_difference));
Available=NewAvailable;
int Index=GetUserMemIndex();
int ToWrite=((int)Size-(int)NbWritten)<Available?Size-NbWritten:Available;

View file

@ -61,69 +61,31 @@ This program is free software: you can redistribute it and/or modify
// PCM FIFO = 64
if(syncwithpwm)
{
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
cbp->length = 4*(16+1);
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++,0,dma_pwm,16+1);
}
else
{
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed PCM
cbp->dst = 0x7E000000 + (PCM_FIFO_A<<2) + PCM_BASE ;
cbp->length = 4*(64+1);
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
cbp++;
SetEasyCB(cbp++,0,dma_pcm,64+1);
}
for (uint32_t samplecnt = 0; samplecnt < buffersize-2; samplecnt++)
{
//Set Amplitude to FSEL for amplitude=0
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
cbp->dst = 0x7E000000 + (GPFSEL0<<2)+GENERAL_BASE;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
SetEasyCB(cbp++,samplecnt*registerbysample,dma_fsel,1);
// Delay
if(syncwithpwm)
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
else
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PCM_TX);
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
if(syncwithpwm)
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
else
cbp->dst = 0x7E000000 + (PCM_FIFO_A<<2) + PCM_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %d pointer %p src %x dest %x next %x\n",samplecnt,cbp,cbp->src,cbp->dst,cbp->next);
cbp++;
SetEasyCB(cbp++,samplecnt*registerbysample,syncwithpwm?dma_pwm:dma_pcm,1);
}
lastcbp=cbp;
// Last CBP before stopping : disable output
sampletab[buffersize*registerbysample-1]=(Originfsel & ~(7 << 12)) | (0 << 12); //Disable Clk
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&usermem[(buffersize*registerbysample-1)]);
cbp->dst = 0x7E000000 + (GPFSEL0<<2)+GENERAL_BASE;
cbp->length = 4;
cbp->stride = 0;
SetEasyCB(cbp,buffersize*registerbysample-1,dma_fsel,1);
cbp->next = 0; // Stop DMA
//fprintf(stderr,"Last cbp %p: src %x dest %x next %x\n",cbp,cbp->src,cbp->dst,cbp->next);
}
void ookburst::SetSymbols(unsigned char *Symbols,uint32_t Size)
{

View file

@ -62,14 +62,7 @@ void serialdmasync::SetDmaAlgo()
for (uint32_t samplecnt = 0; samplecnt < buffersize; samplecnt++)
{
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
SetEasyCB(cbp,samplecnt*registerbysample,dma_pwm,1);
cbp++;
}

14
src/util.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef DEF_UTIL
#define DEF_UTIL
#include <stdio.h>
#include <stdarg.h>
void dbg_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#endif