An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.

Dependencies:   mbed FastIO FastPWM USBDevice

Fork of Pinscape_Controller by Mike R

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleDMA_LPC1768.cpp Source File

SimpleDMA_LPC1768.cpp

00001 #ifdef TARGET_LPC1768
00002 
00003 #include "SimpleDMA.h"
00004 
00005 SimpleDMA *SimpleDMA::irq_owner[8] = {NULL};
00006 LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7};
00007 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination);
00008 
00009 SimpleDMA::SimpleDMA(int channel) {
00010     this->channel(channel);
00011     
00012     //Power up
00013     LPC_SC->PCONP |= 1<<29;
00014     LPC_GPDMA->DMACConfig = 1;
00015     trigger(Trigger_ALWAYS);
00016     
00017     NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0);
00018     NVIC_EnableIRQ(DMA_IRQn);          
00019 }
00020 
00021 int SimpleDMA::start(uint32_t length) {
00022     if (auto_channel)
00023         _channel = getFreeChannel();
00024     else
00025         while(isBusy());
00026     
00027     uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31);
00028     switch (source_size) {
00029         case 16:
00030             control |= (1<<18) | (length >> 1);
00031             break;
00032         case 32:
00033             control |= (2<<18) | (length >> 2);  
00034             break;
00035         default:
00036             control |= length;
00037     }
00038     switch (destination_size) {
00039         case 16:
00040             control |= (1<<21);
00041             break;
00042         case 32:
00043             control |= (2<<21);  
00044             break;
00045     } 
00046     
00047     LPC_GPDMACH[_channel]->DMACCSrcAddr = _source;
00048     LPC_GPDMACH[_channel]->DMACCDestAddr = _destination;
00049     LPC_GPDMACH[_channel]->DMACCLLI = 0;
00050     LPC_GPDMACH[_channel]->DMACCControl = control;     //Enable interrupt also
00051     
00052     irq_owner[_channel] = this;
00053     
00054     if (_trigger != Trigger_ALWAYS) {      
00055         if (_trigger & 16) 
00056             LPC_SC->DMAREQSEL |= 1 << (_trigger - 24);
00057         else
00058             LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24));
00059         
00060         LPC_GPDMACH[_channel]->DMACCConfig = ((_trigger & 15) << 1) + ((_trigger & 15) << 6) + (getTransferType(_trigger, _source, _destination) << 11) +  (1<<15) +1;        //Both parts of the transfer get triggered at same time
00061     } else 
00062         LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15);               //Enable channel
00063     
00064     return 0;
00065 }
00066 
00067 bool SimpleDMA::isBusy( int channel ) {
00068     if (channel == -1)
00069         channel = _channel;
00070     return (LPC_GPDMA->DMACEnbldChns & (1<<channel));
00071 }
00072 
00073 void SimpleDMA::irq_handler0(void) {
00074     while(LPC_GPDMA->DMACIntTCStat != 0) {
00075         
00076     uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF);
00077     if (irq_owner[intloc]!=NULL)
00078         irq_owner[intloc]->irq_handler();
00079     }
00080 }
00081 
00082 void SimpleDMA::irq_handler(void) {
00083     LPC_GPDMA->DMACIntTCClear = 1<<_channel;
00084     _callback.call();
00085 }
00086 
00087 static inline bool isMemory(uint32_t addr)
00088 {
00089     return (addr >> 28) == 0 || (addr >> 28) == 1 || ((addr >= 0x2007C000) && (addr < (0x2007C000 + 0x8000)));
00090 }
00091 
00092 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) {
00093     //If it is always, simply put it on memory-to-memory
00094     if (trig == Trigger_ALWAYS)
00095         return 0;
00096     else if (isMemory(source)) {       //if source is RAM/Flash
00097         if (isMemory(destination))        //if destination is RAM/flash
00098             return 3;                                                               //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do)
00099         else
00100             return 1;                                                               //Source is memory, destination is peripheral, so m2p
00101         }
00102     else {
00103         if (isMemory(destination))
00104             return 2;                                                               //Source is peripheral, destination is memory
00105         else
00106             return 3;                                                               //Both source and destination are peripherals
00107         }
00108         
00109 }
00110 #endif