static void pxa_uart_dma_uninit(struct uart_pxa_port *up) { struct uart_pxa_dma *pxa_dma; pxa_dma = &up->uart_dma; #ifdef CONFIG_PM kfree(pxa_dma->tx_buf_save); #endif stop_dma(up, PXA_UART_TX); stop_dma(up, PXA_UART_RX); if (pxa_dma->txdma_addr != NULL) { dma_free_coherent(up->port.dev, DMA_BLOCK, pxa_dma->txdma_addr, pxa_dma->txdma_addr_phys); pxa_dma->txdma_addr = NULL; } if (pxa_dma->txdma_chan != NULL) { dma_release_channel(pxa_dma->txdma_chan); pxa_dma->txdma_chan = NULL; } if (pxa_dma->rxdma_addr != NULL) { dma_free_coherent(up->port.dev, DMA_BLOCK, pxa_dma->rxdma_addr, pxa_dma->rxdma_addr_phys); pxa_dma->rxdma_addr = NULL; } if (pxa_dma->rxdma_chan != NULL) { dma_release_channel(pxa_dma->rxdma_chan); pxa_dma->rxdma_chan = NULL; } return; }
static int serial_pxa_suspend(struct device *dev) { struct uart_pxa_port *sport = dev_get_drvdata(dev); struct uart_pxa_dma *pxa_dma = &sport->uart_dma; struct dma_tx_state dma_state; if (sport && (sport->ier & UART_IER_DMAE)) { int sent = 0; unsigned long flags; local_irq_save(flags); /* * tx stop and suspend and when resume, * tx startup would be called and set it to 0 */ pxa_dma->tx_stop = 1; pxa_dma->rx_stop = 1; pxa_dma->tx_saved_len = 0; if (dma_async_is_tx_complete(pxa_dma->txdma_chan, pxa_dma->tx_cookie, NULL, NULL) != DMA_SUCCESS) { dmaengine_pause(pxa_dma->txdma_chan); dmaengine_tx_status(pxa_dma->txdma_chan, pxa_dma->tx_cookie, &dma_state); sent = pxa_dma->tx_size - dma_state.residue; pxa_dma->tx_saved_len = dma_state.residue; memcpy(pxa_dma->tx_buf_save, pxa_dma->txdma_addr + sent, dma_state.residue); stop_dma(sport, PXA_UART_TX); } if (dma_async_is_tx_complete(pxa_dma->rxdma_chan, pxa_dma->rx_cookie, NULL, NULL) != DMA_SUCCESS) { dmaengine_pause(pxa_dma->rxdma_chan); pxa_uart_receive_dma_cb(sport); stop_dma(sport, PXA_UART_RX); } local_irq_restore(flags); } if (sport) uart_suspend_port(&serial_pxa_reg, &sport->port); /* Remove uart rx constraint which will block system entering D1p. */ if (del_timer_sync(&sport->pxa_timer)) pxa_timer_handler((unsigned long)sport); return 0; }
static void terminate(int dummy) { stop_dma(); //munmap(virtbase,NUM_PAGES * PAGE_SIZE); printf("END OF PiTx\n"); exit(1); }
static void serial_pxa_stop_rx(struct uart_port *port) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; if (up->dma_enable) { if (up->ier & UART_IER_DMAE) { spin_unlock_irqrestore(&up->port.lock, up->flags); stop_dma(up, PXA_UART_RX); spin_lock_irqsave(&up->port.lock, up->flags); } up->uart_dma.rx_stop = 1; } else { up->ier &= ~UART_IER_RLSI; up->port.read_status_mask &= ~UART_LSR_DR; serial_out(up, UART_IER, up->ier); } }
static int hd_read_udma(block_dev_t *bdev, char *buffer, size_t count, blkno_t blkno) { hd_t *hd; hdc_t *hdc; int sectsleft; int nsects; int result = 0; char *bufp; if (count == 0) { return 0; } bufp = (char *) buffer; hd = (hd_t *) bdev->privdata; hdc = hd->hdc; sectsleft = count / SECTOR_SIZE; while (sectsleft > 0) { /* Select drive */ ide_select_drive(hd); /* Wait for controller ready */ result = ide_wait(hdc, HDCS_DRDY, HDTIMEOUT_DRDY); if (result != 0) { result = -EIO; break; } /* Calculate maximum number of sectors we can transfer */ if (sectsleft > 256) { nsects = 256; } else { nsects = sectsleft; } if (nsects > MAX_DMA_XFER_SIZE / SECTOR_SIZE) { nsects = MAX_DMA_XFER_SIZE / SECTOR_SIZE; } /* Prepare transfer */ result = 0; hdc->dir = HD_XFER_DMA; hdc->active = hd; hd_setup_transfer(hd, blkno, nsects); /* Setup DMA */ setup_dma(hdc, bufp, nsects * SECTOR_SIZE, BM_CR_WRITE); /* Start read */ outb(HDCMD_READDMA, hdc->iobase + HDC_COMMAND); start_dma(hdc); /* Stop DMA channel and check DMA status */ result = stop_dma(hdc); if (result < 0) { break; } /* Check controller status */ if (hdc->status & HDCS_ERR) { result = -EIO; break; } /* Advance to next */ sectsleft -= nsects; bufp += nsects * SECTOR_SIZE; } /* Cleanup */ hdc->dir = HD_XFER_IDLE; hdc->active = NULL; return result == 0 ? count : result; }
int pitx_run( const char Mode, int SampleRate, const float SetFrequency, const float ppmpll, const char NoUsePwmFrequency, ssize_t (*readWrapper)(void *buffer, size_t count), void (*reset)(void), int* skipSignals) { int i; //char pagemap_fn[64]; int OffsetModulation=1000;//TBR int MicGain=100; //unsigned char *data; //Specific to ModeIQ static signed short *IQArray=NULL; //Specific to ModeIQ_FLOAT static float *IQFloatArray=NULL; //Specific to Mode RF typedef struct { double Frequency; uint32_t WaitForThisSample; } samplerf_t; samplerf_t *TabRfSample=NULL; fprintf(stdout,"rpitx Version %s compiled %s (F5OEO Evariste) running on ",PROGRAM_VERSION,__DATE__); // Init Plls Frequency using ppm (or default) PllFreq500MHZ=PLL_FREQ_500MHZ; PllFreq500MHZ+=PllFreq500MHZ * (ppmpll / 1000000.0); PllFreq1GHZ=PLL_FREQ_1GHZ; PllFreq1GHZ+=PllFreq1GHZ * (ppmpll / 1000000.0); PllFreq19MHZ=PLLFREQ_192; PllFreq19MHZ+=PllFreq19MHZ * (ppmpll / 1000000.0); //End of Init Plls if(Mode==MODE_IQ) { IQArray=malloc(DmaSampleBurstSize*2*sizeof(signed short)); // TODO A FREE AT THE END OF SOFTWARE reset(); } if(Mode==MODE_IQ_FLOAT) { IQFloatArray=malloc(DmaSampleBurstSize*2*sizeof(float)); // TODO A FREE AT THE END OF SOFTWARE } if((Mode==MODE_RF)||(Mode==MODE_RFA)) { //TabRfSample=malloc(DmaSampleBurstSize*sizeof(samplerf_t)); SampleRate=100000L; //NOT USED BUT BY CALCULATING TIMETOSLEEP IN RF MODE } if(Mode==MODE_VFO) SampleRate=50000L; //50000 BY EXPERIMENT if(Mode==MODE_IQ) { printf(" Frequency=%f ",GlobalTuningFrequency); printf(" SampleRate=%d ",SampleRate); } pitx_SetTuneFrequency(SetFrequency*1000.0); pitx_init(SampleRate, GlobalTuningFrequency, skipSignals); static volatile uint32_t cur_cb,last_cb; int last_sample; int this_sample; int free_slots; //int SumDelay=0; long int start_time; static long time_difference=0; struct timespec gettime_now; cur_cb = (uint32_t)virtbase+ (NUM_SAMPLES-DmaSampleBurstSize)* sizeof(dma_cb_t) *CBS_SIZE_BY_SAMPLE; last_cb=(uint32_t)virtbase /*+ 965* sizeof(dma_cb_t) *CBS_SIZE_BY_SAMPLE*/ ; dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys((void*)cur_cb); unsigned char Init=1; // ----------------------------------------------------------------- for (;;) { int TimeToSleep; static int StatusCompteur=0; cur_cb = mem_phys_to_virt((uint32_t)(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40])); this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE); last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE); free_slots = this_sample - last_sample; if (free_slots < 0) // WARNING : ORIGINAL CODE WAS < strictly free_slots += NUM_SAMPLES; //printf("last_sample %lx cur_cb %lx FreeSlots = %d Time to sleep=%d\n",last_sample,cur_cb,free_slots,TimeToSleep); if(Init==0) { TimeToSleep=(1e6*(NUM_SAMPLES-free_slots*2))/SampleRate; // Time to sleep in us //printf("TimeToSleep%d\n",TimeToSleep); } else TimeToSleep=1000; //printf("Buffer Available=%d\n",BufferAvailable()); clock_gettime(CLOCK_REALTIME, &gettime_now); start_time = gettime_now.tv_nsec; if(TimeToSleep>=(2200+KERNEL_GRANULARITY)) // 2ms : Time to process File/Canal Coding { udelay(TimeToSleep-(2200+KERNEL_GRANULARITY)); TimeToSleep=0; } else { //udelay(TimeToSleep); sched_yield(); //TimeToSleep=0; //if(free_slots>(NUM_SAMPLES*9/10)) //printf("Buffer nearly empty...%d/%d\n",free_slots,NUM_SAMPLES); } static int free_slots_now; cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]); this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE); last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE); free_slots_now = this_sample - last_sample; if (free_slots_now < 0) // WARNING : ORIGINAL CODE WAS < strictly free_slots_now += NUM_SAMPLES; clock_gettime(CLOCK_REALTIME, &gettime_now); time_difference = gettime_now.tv_nsec - start_time; if(time_difference<0) time_difference+=1E9; if(StatusCompteur%10==0) { //printf(" DiffTime = %ld FreeSlot %d FreeSlotDiff=%d Bitrate : %f\n",time_difference,free_slots_now,free_slots_now-free_slots,(1e9*(free_slots_now-free_slots))/(float)time_difference); } //if((1e9*(free_slots_now-free_slots))/(float)time_difference<40100.0) printf("Drift BAD\n"); else printf("Drift GOOD\n"); StatusCompteur++; free_slots=free_slots_now; // FIX IT : Max(freeslot et Numsample/8) if((Init==1)&&(free_slots < DmaSampleBurstSize /*NUM_SAMPLES/8*/)) { printf("****** STARTING TRANSMIT ********\n"); dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys((void*)virtbase ); usleep(100); //Start DMA PWMFrequency //dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = 0x10880001; //Start Main DMA dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10FF0001; // go, mid priority, wait for outstanding writes :7 Seems Max Priority Init=0; continue; } clock_gettime(CLOCK_REALTIME, &gettime_now); start_time = gettime_now.tv_nsec; int debug=0; if ((free_slots>=DmaSampleBurstSize)) { // *************************************** MODE IQ ************************************************** if(Mode==MODE_IQ) { int NbRead=0; static int Max=0; static int Min=32767; static int CompteSample=0; CompteSample++; NbRead=readWrapper(IQArray,DmaSampleBurstSize*2*2/*SHORT I,SHORT Q*/); if(NbRead!=DmaSampleBurstSize*2*2) { if(loop_mode_flag==1) { printf("Looping FileIn\n"); reset(); NbRead=readWrapper(IQArray,DmaSampleBurstSize*2*2); } else { stop_dma(); return 0; } } for(i=0;i<DmaSampleBurstSize;i++) { //static float samplerate=48000; static int amp; static double df; int CorrectionRpiFrequency=-1000; //TODO PPM / Offset=1KHZ at 144MHZ CompteSample++; //printf("i%d q%d\n",IQArray[2*i],IQArray[2*i+1]); IQToFreqAmp(IQArray[2*i+1],IQArray[2*i],&df,&,SampleRate); // Compression have to be done in modulation (SSB not here) double A = 87.7f; // compression parameter double ampf=amp/32767.0; ampf = (fabs(ampf) < 1.0f/A) ? A*fabs(ampf)/(1.0f+ln(A)) : (1.0f+ln(A*fabs(ampf)))/(1.0f+ln(A)); //compand amp= (int)(round(ampf * 32767.0f)) ; if(amp>Max) Max=amp; if(amp<Min) Min=amp; /* if((CompteSample%4800)==0) { //printf("%d\n",((CompteSample/48000)*1024)%32767); //printf("Amp %d Freq %f MinAmp %d MaxAmp %d\n",amp,df,Min,Max); printf("%d;%d;%d;%f\n",IQArray[2*i+1],IQArray[2*i],amp,df); // printf("."); fflush(stdout); } */ // TEST - WARNING, REMOVE FOR RELEASE //amp=((CompteSample/48000)*1024)%32767; //df=0; //amp=amp*10; //amp=32767; //if(df<OffsetModulation+100) amp=0; //if(amp<32767/8) df= OffsetModulation; // // FIXME : df/harmonicNumber could alterate maybe modulations FrequencyAmplitudeToRegister((GlobalTuningFrequency-OffsetModulation+/*(CompteSample/480)*/+df/HarmonicNumber)/HarmonicNumber,amp,last_sample++,0,SampleRate,NoUsePwmFrequency,CompteSample%2); // !!!!!!!!!!!!!!!!!!!! 680 is for 48KHZ , should be adpated !!!!!!!!!!!!!!!!! free_slots--; if (last_sample == NUM_SAMPLES) last_sample = 0; } } // *************************************** MODE IQ FLOAT************************************************** if(Mode==MODE_IQ_FLOAT) { int NbRead=0; static int Max=0; static int Min=32767; static int CompteSample=0; CompteSample++; NbRead=readWrapper(IQFloatArray,DmaSampleBurstSize*2*sizeof(float)); if(NbRead!=DmaSampleBurstSize*2*sizeof(float)) { if(loop_mode_flag==1) { printf("Looping FileIn\n"); reset(); } else if (!useStdin) { stop_dma(); return 0; } } for(i=0;i<DmaSampleBurstSize;i++) { //static float samplerate=48000; static int amp; static double df; int CorrectionRpiFrequency=-1000; //TODO PPM / Offset=1KHZ at 144MHZ CompteSample++; //printf("i%d q%d\n",IQArray[2*i],IQArray[2*i+1]); IQToFreqAmp(IQFloatArray[2*i+1]*32767,IQFloatArray[2*i]*32767,&df,&,SampleRate); if(amp>Max) Max=amp; if(amp<Min) Min=amp; /* if((CompteSample%4800)==0) { //printf("%d\n",((CompteSample/48000)*1024)%32767); printf("Amp %d Freq %f MinAmp %d MaxAmp %d\n",amp,df,Min,Max); // printf("."); fflush(stdout); } */ // TEST - WARNING, REMOVE FOR RELEASE //amp=((CompteSample/48000)*1024)%32767; //df=0; //amp=amp*10; //amp=32767; //if(df<OffsetModulation+100) amp=0; // //amp=32767; //if(df>SampleRate/2) df=SampleRate/2-df; FrequencyAmplitudeToRegister((GlobalTuningFrequency-OffsetModulation+df/HarmonicNumber)/HarmonicNumber,amp,last_sample++,0,SampleRate,NoUsePwmFrequency,CompteSample%2); free_slots--; if (last_sample == NUM_SAMPLES) last_sample = 0; } } // *************************************** MODE RF ************************************************** if((Mode==MODE_RF)||(Mode==MODE_RFA)) { // SHOULD NOT EXEED 200 STEP*500ns; SAMPLERATE SHOULD BE MAX TO HAVE PRECISION FOR PCM // BUT FIFO OF PCM IS 16 : SAMPLERATE MAYBE NOT EXCESS 16*80000 ! CAREFULL BUGS HERE #define MAX_DELAY_WAIT 25000 static int CompteSample=0; static uint32_t TimeRemaining=0; static samplerf_t SampleRf; static int NbRead; CompteSample++; int i; for(i=0;i<DmaSampleBurstSize;i++) { if(TimeRemaining==0) { NbRead=readWrapper(&SampleRf,sizeof(samplerf_t)); if(NbRead!=sizeof(samplerf_t)) { if(loop_mode_flag==1) { //printf("Looping FileIn\n"); reset(); NbRead=readWrapper(&SampleRf,sizeof(samplerf_t)); } else if (!useStdin) { stop_dma(); return 0; } } TimeRemaining=SampleRf.WaitForThisSample; //TimeRemaining=50000;//SampleRf.WaitForThisSample; debug=1; //printf("A=%f Time =%d \n",SampleRf.Frequency,SampleRf.WaitForThisSample); } else debug=0; static int amp=32767; static int WaitSample=0; if(TimeRemaining>MAX_DELAY_WAIT) WaitSample=MAX_DELAY_WAIT; else WaitSample=TimeRemaining; //printf("TimeRemaining %d WaitSample %d\n",TimeRemaining,WaitSample); if(Mode==MODE_RF) { if(SampleRf.Frequency==0.0) { amp=0; SampleRf.Frequency=00.0;// TODO change that ugly frequency } else amp=32767; FrequencyAmplitudeToRegister((SampleRf.Frequency/HarmonicNumber+GlobalTuningFrequency)/HarmonicNumber,amp,last_sample++,WaitSample,0,NoUsePwmFrequency,debug); } if(Mode==MODE_RFA) FrequencyAmplitudeToRegister((GlobalTuningFrequency)/HarmonicNumber,SampleRf.Frequency,last_sample++,WaitSample,0,NoUsePwmFrequency,debug); TimeRemaining-=WaitSample; free_slots--; if (last_sample == NUM_SAMPLES) last_sample = 0; } } // *************************************** MODE VFO ************************************************** if(Mode==MODE_VFO) { static uint32_t CompteSample=0; int i; //printf("Begin free %d\n",free_slots); for(i=0;i<DmaSampleBurstSize;i++) { //To be fine tuned !!!! static int OutputPower=32767; CompteSample++; debug=1;//(debug+1)%2; //OutputPower=(CompteSample/10)%32768; FrequencyAmplitudeToRegister(GlobalTuningFrequency/HarmonicNumber/*+(CompteSample*0.1)*/,OutputPower,last_sample++,25000,0,NoUsePwmFrequency,debug); free_slots--; //printf("%f \n",GlobalTuningFrequency+(((CompteSample/10)*1)%50000)); if (last_sample == NUM_SAMPLES) last_sample = 0; if(CompteSample%40000==0) { //OutputPower=(OutputPower+1)%8; //pad_gpios_reg[PADS_GPIO_0] = 0x5a000000 + (OutputPower&0x7) + (1<<4) + (0<<3); // Set output power for I/Q GPIO18/GPIO19 //printf("Freq %d Outputpower=%d\n",CompteSample/20000,OutputPower); } //usleep(1); } //printf("End free %d\n",free_slots); } } clock_gettime(CLOCK_REALTIME, &gettime_now); time_difference = gettime_now.tv_nsec - start_time; if(time_difference<0) time_difference+=1E9; last_cb = (uint32_t)virtbase + last_sample * sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE; } stop_dma(); return(0); }
static inline void dma_receive_chars(struct uart_pxa_port *up, int *status) { struct tty_port *port = &up->port.state->port; unsigned char ch; int max_count = 256; int count = 0; unsigned char *tmp; unsigned int flag = TTY_NORMAL; struct uart_pxa_dma *pxa_dma = &up->uart_dma; struct dma_tx_state dma_state; /* * Pause DMA channel and deal with the bytes received by DMA */ dmaengine_pause(pxa_dma->rxdma_chan); dmaengine_tx_status(pxa_dma->rxdma_chan, pxa_dma->rx_cookie, &dma_state); count = DMA_BLOCK - dma_state.residue; tmp = pxa_dma->rxdma_addr; if (up->port.sysrq) { while (count > 0) { if (!uart_handle_sysrq_char(&up->port, *tmp)) { uart_insert_char(&up->port, *status, 0, *tmp, flag); up->port.icount.rx++; } tmp++; count--; } } else { tty_insert_flip_string(port, tmp, count); up->port.icount.rx += count; } /* deal with the bytes in rx FIFO */ do { ch = serial_in(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE | UART_LSR_OE))) { /* * For statistics only */ if (*status & UART_LSR_BI) { *status &= ~(UART_LSR_FE | UART_LSR_PE); up->port.icount.brk++; /* * We do the SysRQ and SAK checking * here because otherwise the break * may get masked by ignore_status_mask * or read_status_mask. */ if (uart_handle_break(&up->port)) goto ignore_char2; } else if (*status & UART_LSR_PE) { up->port.icount.parity++; } else if (*status & UART_LSR_FE) { up->port.icount.frame++; } if (*status & UART_LSR_OE) up->port.icount.overrun++; /* * Mask off conditions which should be ignored. */ *status &= up->port.read_status_mask; #ifdef CONFIG_SERIAL_PXA_CONSOLE if (up->port.line == up->port.cons->index) { /* Recover the break flag from console xmit */ *status |= up->lsr_break_flag; up->lsr_break_flag = 0; } #endif if (*status & UART_LSR_BI) flag = TTY_BREAK; else if (*status & UART_LSR_PE) flag = TTY_PARITY; else if (*status & UART_LSR_FE) flag = TTY_FRAME; } if (!uart_handle_sysrq_char(&up->port, ch)) uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); ignore_char2: *status = serial_in(up, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); tty_schedule_flip(port); stop_dma(up, 1); if (pxa_dma->rx_stop) return; pxa_uart_receive_dma_start(up); }