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
SimpleDMA.h
00001 #ifndef SIMPLEDMA_H 00002 #define SIMPLEDMA_H 00003 00004 #ifdef RTOS_H 00005 #include "rtos.h" 00006 #endif 00007 00008 #include "mbed.h" 00009 #include "SimpleDMA_KL25.h" 00010 #include "SimpleDMA_KL46.h" 00011 #include "SimpleDMA_LPC1768.h" 00012 00013 00014 /** 00015 * SimpleDMA, DMA made simple! (Okay that was bad) 00016 * 00017 * A class to easily make basic DMA operations happen. Not all features 00018 * of the DMA peripherals are used, but the main ones are: From and to memory 00019 * and peripherals, either continiously or triggered 00020 */ 00021 class SimpleDMA { 00022 public: 00023 /** 00024 * Constructor 00025 * 00026 * @param channel - optional parameter which channel should be used, default is automatic channel selection 00027 */ 00028 SimpleDMA(int channel = -1); 00029 00030 /** 00031 * Set the source of the DMA transfer 00032 * 00033 * Autoincrement increments the pointer after each transfer. If the source 00034 * is an array this should be true, if it is a peripheral or a single memory 00035 * location it should be false. 00036 * 00037 * The source can be any pointer to any memory location. Automatically 00038 * the wordsize is calculated depending on the type, if required you can 00039 * also override this. 00040 * 00041 * @param pointer - pointer to the memory location 00042 * @param autoinc - should the pointer be incremented by the DMA module 00043 * @param size - wordsize in bits (optional, generally can be omitted) 00044 * @return - 0 on success 00045 */ 00046 template<typename Type> 00047 void source(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) { 00048 _source = (uint32_t)pointer; 00049 source_inc = autoinc; 00050 source_size = size; 00051 } 00052 00053 /** 00054 * Set the destination of the DMA transfer 00055 * 00056 * Autoincrement increments the pointer after each transfer. If the source 00057 * is an array this should be true, if it is a peripheral or a single memory 00058 * location it should be false. 00059 * 00060 * The destination can be any pointer to any memory location. Automatically 00061 * the wordsize is calculated depending on the type, if required you can 00062 * also override this. 00063 * 00064 * @param pointer - pointer to the memory location 00065 * @param autoinc - should the pointer be incremented by the DMA module 00066 * @param size - wordsize in bits (optional, generally can be omitted) 00067 * @return - 0 on success 00068 */ 00069 template<typename Type> 00070 void destination(Type* pointer, bool autoinc, int size = sizeof(Type) * 8) { 00071 _destination = (uint32_t)pointer; 00072 destination_inc = autoinc; 00073 destination_size = size; 00074 } 00075 00076 00077 /** 00078 * Set the trigger for the DMA operation 00079 * 00080 * In SimpleDMA_[yourdevice].h you can find the names of the different triggers. 00081 * Trigger_ALWAYS is defined for all devices, it will simply move the data 00082 * as fast as possible. Used for memory-memory transfers. If nothing else is set 00083 * that will be used by default. 00084 * 00085 * @param trig - trigger to use 00086 * @param return - 0 on success 00087 */ 00088 void trigger(SimpleDMA_Trigger trig) { 00089 _trigger = trig; 00090 } 00091 00092 /** 00093 * Set the DMA channel 00094 * 00095 * Generally you will not need to call this function, the constructor does so for you 00096 * 00097 * @param chan - DMA channel to use, -1 = variable channel (highest priority channel which is available) 00098 */ 00099 void channel(int chan); 00100 int getChannel() { return _channel; } 00101 00102 /** 00103 * Start the transfer 00104 * 00105 * @param length - number of BYTES to be moved by the DMA 00106 */ 00107 int start(uint32_t length, bool wait); 00108 00109 /** 00110 * Prepare a transfer. This sets everything up for a transfer, but leaves it up 00111 * to the caller to trigger the start of the transfer. This gives the caller 00112 * precise control over the timing of the transfer, for transfers that must be 00113 * synchronized with other functions. To start the DMA transfer, the caller 00114 * must simply "OR" DMAMUX_CHCFG_ENBL_MASK into the byte at the returned 00115 * address. 00116 */ 00117 volatile uint8_t *prepare(uint32_t length, bool wait); 00118 00119 /** 00120 * Is the DMA channel busy 00121 * 00122 * @param channel - channel to check, -1 = current channel 00123 * @return - true if it is busy 00124 */ 00125 bool isBusy( int channel = -1 ); 00126 00127 /** 00128 * Number of bytes remaining in running transfer. This reads the controller 00129 * register with the remaining byte count, which the hardware updates each 00130 * time it completes a destination transfer. 00131 */ 00132 uint32_t remaining(int channel = -1); 00133 00134 /** 00135 * Attach an interrupt upon completion of DMA transfer or error 00136 * 00137 * @param function - function to call upon completion (may be a member function) 00138 */ 00139 void attach(void (*function)(void)) { 00140 _callback.attach(function); 00141 } 00142 00143 template<typename T> 00144 void attach(T *object, void (T::*member)(void)) { 00145 _callback.attach(object, member); 00146 } 00147 00148 /** 00149 * Link to another channel. This triggers the given destination 00150 * channel when a transfer on this channel is completed. If 'all' 00151 * is true, the link occurs after the entire transfer is complete 00152 * (i.e., the byte count register in this channel reaches zero). 00153 * Otherwise, the link is triggered once for each transfer on this 00154 * channel. 00155 */ 00156 void link(SimpleDMA &dest, bool all = false); 00157 00158 /** 00159 * Link to two other channels. This triggers the 'dest1' channel 00160 * once for each transfer on this channel, and then triggers the 00161 * 'dest2' channel once when the entire transfer has been completed 00162 * (i.e., the byte count register on this channel reaches zero). 00163 */ 00164 void link(SimpleDMA &dest1, SimpleDMA &dest2); 00165 00166 00167 #ifdef RTOS_H 00168 /** 00169 * Start a DMA transfer similar to start, however block current Thread 00170 * until the transfer is finished 00171 * 00172 * When using this function only the current Thread is halted. 00173 * The Thread is moved to Waiting state: other Threads will continue 00174 * to run normally. 00175 * 00176 * This function is only available if you included rtos.h before 00177 * including SimpleDMA.h. 00178 * 00179 * @param length - number of BYTES to be moved by the DMA 00180 */ 00181 void wait(int length) { 00182 id = Thread::gettid(); 00183 this->attach(this, &SimpleDMA::waitCallback); 00184 this->start(length); 00185 Thread::signal_wait(0x1); 00186 } 00187 #endif 00188 00189 protected: 00190 uint8_t _channel; 00191 SimpleDMA_Trigger _trigger; 00192 uint32_t _source; 00193 uint32_t _destination; 00194 uint8_t source_size; 00195 uint8_t destination_size; 00196 uint8_t linkChannel1; 00197 uint8_t linkChannel2; 00198 bool source_inc : 1; 00199 bool destination_inc : 1; 00200 bool auto_channel : 1; 00201 uint8_t linkMode : 2; 00202 00203 00204 //IRQ handlers 00205 FunctionPointer _callback; 00206 void irq_handler(void); 00207 00208 static SimpleDMA *irq_owner[DMA_CHANNELS]; 00209 00210 static void class_init(); 00211 static void irq_handler0( void ); 00212 00213 #if DMA_IRQS > 1 00214 static void irq_handler1( void ); 00215 static void irq_handler2( void ); 00216 static void irq_handler3( void ); 00217 #endif 00218 00219 //Keep searching until we find a non-busy channel, start with lowest channel number 00220 int getFreeChannel(void); 00221 00222 #ifdef RTOS_H 00223 osThreadId id; 00224 void waitCallback(void) { 00225 osSignalSet(id, 0x1); 00226 } 00227 #endif 00228 }; 00229 #endif
Generated on Wed Jul 13 2022 03:30:11 by 1.7.2