Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FastIO FastPWM USBDevice
Fork of Pinscape_Controller by
SimpleDMA/SimpleDMA_LPC1768.cpp@97:fc7727303038, 2018-02-07 (annotated)
- Committer:
- mjr
- Date:
- Wed Feb 07 00:01:21 2018 +0000
- Revision:
- 97:fc7727303038
- Parent:
- 45:c42166b2878c
Added IR protocol support for TCL Roku TV models
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| mjr | 45:c42166b2878c | 1 | #ifdef TARGET_LPC1768 |
| mjr | 45:c42166b2878c | 2 | |
| mjr | 45:c42166b2878c | 3 | #include "SimpleDMA.h" |
| mjr | 45:c42166b2878c | 4 | |
| mjr | 45:c42166b2878c | 5 | SimpleDMA *SimpleDMA::irq_owner[8] = {NULL}; |
| mjr | 45:c42166b2878c | 6 | LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7}; |
| mjr | 45:c42166b2878c | 7 | uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination); |
| mjr | 45:c42166b2878c | 8 | |
| mjr | 45:c42166b2878c | 9 | SimpleDMA::SimpleDMA(int channel) { |
| mjr | 45:c42166b2878c | 10 | this->channel(channel); |
| mjr | 45:c42166b2878c | 11 | |
| mjr | 45:c42166b2878c | 12 | //Power up |
| mjr | 45:c42166b2878c | 13 | LPC_SC->PCONP |= 1<<29; |
| mjr | 45:c42166b2878c | 14 | LPC_GPDMA->DMACConfig = 1; |
| mjr | 45:c42166b2878c | 15 | trigger(Trigger_ALWAYS); |
| mjr | 45:c42166b2878c | 16 | |
| mjr | 45:c42166b2878c | 17 | NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0); |
| mjr | 45:c42166b2878c | 18 | NVIC_EnableIRQ(DMA_IRQn); |
| mjr | 45:c42166b2878c | 19 | } |
| mjr | 45:c42166b2878c | 20 | |
| mjr | 45:c42166b2878c | 21 | int SimpleDMA::start(uint32_t length) { |
| mjr | 45:c42166b2878c | 22 | if (auto_channel) |
| mjr | 45:c42166b2878c | 23 | _channel = getFreeChannel(); |
| mjr | 45:c42166b2878c | 24 | else |
| mjr | 45:c42166b2878c | 25 | while(isBusy()); |
| mjr | 45:c42166b2878c | 26 | |
| mjr | 45:c42166b2878c | 27 | uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31); |
| mjr | 45:c42166b2878c | 28 | switch (source_size) { |
| mjr | 45:c42166b2878c | 29 | case 16: |
| mjr | 45:c42166b2878c | 30 | control |= (1<<18) | (length >> 1); |
| mjr | 45:c42166b2878c | 31 | break; |
| mjr | 45:c42166b2878c | 32 | case 32: |
| mjr | 45:c42166b2878c | 33 | control |= (2<<18) | (length >> 2); |
| mjr | 45:c42166b2878c | 34 | break; |
| mjr | 45:c42166b2878c | 35 | default: |
| mjr | 45:c42166b2878c | 36 | control |= length; |
| mjr | 45:c42166b2878c | 37 | } |
| mjr | 45:c42166b2878c | 38 | switch (destination_size) { |
| mjr | 45:c42166b2878c | 39 | case 16: |
| mjr | 45:c42166b2878c | 40 | control |= (1<<21); |
| mjr | 45:c42166b2878c | 41 | break; |
| mjr | 45:c42166b2878c | 42 | case 32: |
| mjr | 45:c42166b2878c | 43 | control |= (2<<21); |
| mjr | 45:c42166b2878c | 44 | break; |
| mjr | 45:c42166b2878c | 45 | } |
| mjr | 45:c42166b2878c | 46 | |
| mjr | 45:c42166b2878c | 47 | LPC_GPDMACH[_channel]->DMACCSrcAddr = _source; |
| mjr | 45:c42166b2878c | 48 | LPC_GPDMACH[_channel]->DMACCDestAddr = _destination; |
| mjr | 45:c42166b2878c | 49 | LPC_GPDMACH[_channel]->DMACCLLI = 0; |
| mjr | 45:c42166b2878c | 50 | LPC_GPDMACH[_channel]->DMACCControl = control; //Enable interrupt also |
| mjr | 45:c42166b2878c | 51 | |
| mjr | 45:c42166b2878c | 52 | irq_owner[_channel] = this; |
| mjr | 45:c42166b2878c | 53 | |
| mjr | 45:c42166b2878c | 54 | if (_trigger != Trigger_ALWAYS) { |
| mjr | 45:c42166b2878c | 55 | if (_trigger & 16) |
| mjr | 45:c42166b2878c | 56 | LPC_SC->DMAREQSEL |= 1 << (_trigger - 24); |
| mjr | 45:c42166b2878c | 57 | else |
| mjr | 45:c42166b2878c | 58 | LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24)); |
| mjr | 45:c42166b2878c | 59 | |
| mjr | 45:c42166b2878c | 60 | 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 |
| mjr | 45:c42166b2878c | 61 | } else |
| mjr | 45:c42166b2878c | 62 | LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15); //Enable channel |
| mjr | 45:c42166b2878c | 63 | |
| mjr | 45:c42166b2878c | 64 | return 0; |
| mjr | 45:c42166b2878c | 65 | } |
| mjr | 45:c42166b2878c | 66 | |
| mjr | 45:c42166b2878c | 67 | bool SimpleDMA::isBusy( int channel ) { |
| mjr | 45:c42166b2878c | 68 | if (channel == -1) |
| mjr | 45:c42166b2878c | 69 | channel = _channel; |
| mjr | 45:c42166b2878c | 70 | return (LPC_GPDMA->DMACEnbldChns & (1<<channel)); |
| mjr | 45:c42166b2878c | 71 | } |
| mjr | 45:c42166b2878c | 72 | |
| mjr | 45:c42166b2878c | 73 | void SimpleDMA::irq_handler0(void) { |
| mjr | 45:c42166b2878c | 74 | while(LPC_GPDMA->DMACIntTCStat != 0) { |
| mjr | 45:c42166b2878c | 75 | |
| mjr | 45:c42166b2878c | 76 | uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF); |
| mjr | 45:c42166b2878c | 77 | if (irq_owner[intloc]!=NULL) |
| mjr | 45:c42166b2878c | 78 | irq_owner[intloc]->irq_handler(); |
| mjr | 45:c42166b2878c | 79 | } |
| mjr | 45:c42166b2878c | 80 | } |
| mjr | 45:c42166b2878c | 81 | |
| mjr | 45:c42166b2878c | 82 | void SimpleDMA::irq_handler(void) { |
| mjr | 45:c42166b2878c | 83 | LPC_GPDMA->DMACIntTCClear = 1<<_channel; |
| mjr | 45:c42166b2878c | 84 | _callback.call(); |
| mjr | 45:c42166b2878c | 85 | } |
| mjr | 45:c42166b2878c | 86 | |
| mjr | 45:c42166b2878c | 87 | static inline bool isMemory(uint32_t addr) |
| mjr | 45:c42166b2878c | 88 | { |
| mjr | 45:c42166b2878c | 89 | return (addr >> 28) == 0 || (addr >> 28) == 1 || ((addr >= 0x2007C000) && (addr < (0x2007C000 + 0x8000))); |
| mjr | 45:c42166b2878c | 90 | } |
| mjr | 45:c42166b2878c | 91 | |
| mjr | 45:c42166b2878c | 92 | uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) { |
| mjr | 45:c42166b2878c | 93 | //If it is always, simply put it on memory-to-memory |
| mjr | 45:c42166b2878c | 94 | if (trig == Trigger_ALWAYS) |
| mjr | 45:c42166b2878c | 95 | return 0; |
| mjr | 45:c42166b2878c | 96 | else if (isMemory(source)) { //if source is RAM/Flash |
| mjr | 45:c42166b2878c | 97 | if (isMemory(destination)) //if destination is RAM/flash |
| mjr | 45:c42166b2878c | 98 | return 3; //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do) |
| mjr | 45:c42166b2878c | 99 | else |
| mjr | 45:c42166b2878c | 100 | return 1; //Source is memory, destination is peripheral, so m2p |
| mjr | 45:c42166b2878c | 101 | } |
| mjr | 45:c42166b2878c | 102 | else { |
| mjr | 45:c42166b2878c | 103 | if (isMemory(destination)) |
| mjr | 45:c42166b2878c | 104 | return 2; //Source is peripheral, destination is memory |
| mjr | 45:c42166b2878c | 105 | else |
| mjr | 45:c42166b2878c | 106 | return 3; //Both source and destination are peripherals |
| mjr | 45:c42166b2878c | 107 | } |
| mjr | 45:c42166b2878c | 108 | |
| mjr | 45:c42166b2878c | 109 | } |
| mjr | 45:c42166b2878c | 110 | #endif |
