test codes to test DMA features

Dependencies:   mDMA mbed

Revision:
0:9b2f77afaacd
Child:
1:5b946b818a29
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 09 21:47:50 2015 +0000
@@ -0,0 +1,655 @@
+/**
+M2M : read content from a files using CPU, test the time; read content from a file using DMA. Compare the content
+M2P : demenstrate while DMA-UART working, LED swtich is also working 
+P2M : demenstrate m2m, m2p, p2m, could work together ; keep sending 
+P2P
+ 
+Do we need constructor?
+Select which ever free or which ever not declared?
+How to put comments?
+
+
+Done 1. make init struct generic -- Done
+2. make trigger type generic .-- Done
+3. support pass method callback -- no solution 
+4. read_adc -- Done
+5. PC app to received data from uart
+6. start ADC transfer rate
+7. trigger on Timer 
+8. Add assert --- Done
+9. Destructor - Done 
+10. add space/ comments  
+*/
+
+// disassembler memcpy
+#include "mbed.h"
+#include "dma.h"
+
+#define test_attach 1
+#define test_m2m 0
+#define test_m2m_int 0
+#define test_m2p 0
+#define test_p2m 0
+#define test_p2p 0
+#define test_all 0
+#define test_adc 0
+#define test_LLI 0
+
+
+LocalFileSystem local("local");
+
+DigitalOut myled1(LED1);
+DigitalOut myled2(LED2);
+DigitalOut myled3(LED3);
+DigitalOut myled4(LED4);
+
+// Use Timer to measure the execution time
+Timer t;
+
+RawSerial pc (USBTX, USBRX);
+
+// Callbacks for DMA interrupts
+void led_switchon_m2m(void);
+void led_switchon_m2p (void);
+void led_switchon_p2m (void);
+void led_switchon_p2p (void);
+void led_show (void);
+void IRQ_err (void);
+
+
+void ADC_init();
+void old_ADC_init();
+void burst_ADC_init();
+uint32_t ADC_read(uint8_t channel);
+
+
+volatile bool m2p_finishFlag = 0; 
+
+class mynumber {
+    public:
+        int num;
+        mynumber(){
+            num = 0;
+        }
+        void print_mynumber(void){
+            pc.printf("my number is %d", num);
+        }
+    
+};
+
+mynumber mynumber1;
+
+void test_mynumber (){
+     static_cast<mynumber*>(&mynumber1)->print_mynumber();
+}
+
+
+template<typename T>
+void led_test_call (T *object, void (T::*member)(void)){
+    void (T::*m)(void);
+    T* o = static_cast<T*>(object);
+    memcpy((char*)&m, (char*)&member, sizeof(m));
+    (o->*m)();
+}
+
+mynumber mynumber2;
+
+void irq_handler(void)
+{
+    led_test_call<mynumber> (&mynumber2, &mynumber::print_mynumber);
+}
+
+
+
+int main(void)
+{
+char src[] =        
+                                    "Hello world Copy the logical and implementation_tsmc28hpm directories in to the Skadi home directo \r\n" \
+                                    "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "(for instance address 0x12345678 could hold a value of 0xffffffff and then 0x12345679 could hold a completely  \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word\r\n"\
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it  or add a restriction.\r\n" 
+                                    "Hello world Copy the logical and implementation_tsmc28hpm directories in to the Skadi home directo \r\n" \
+                                    "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "(for instance address 0x12345678 could hold a value of 0xffffffff and then 0x12345679 could hold a completely  \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word \r\n" \
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it or add a restriction.  \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word\r\n" \
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it or add a restriction.\r\n"\
+                                    "Hello world Copy the logical and implementation_tsmc28hpm directories in to the Skadi home directo \r\n"\
+                                    "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "(for instance address 0x12345678 could hold a value of 0xffffffff and then 0x12345679 could hold a completely  \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word \r\n" \
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it or add a restriction.  \r\n" \
+                                  "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "Hello world Copy the logical and implementation_tsmc28hpm directories in to the Skadi home directo \r\n" \
+                                    "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "(for instance address 0x12345678 could hold a value of 0xffffffff and then 0x12345679 could hold a completely  \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word \r\n" \
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it or add a restriction.  \r\n" \
+                                  "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how\r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "(for instance address 0x12345678 could hold a value of 0xffffffff and then 0x12345679 could hold a completely \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word \r\n" \
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it or add a restriction. \r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "(for instance address 0x12345678 could hold a value of 0xffffffff and then 0x12345679 could hold a completely  \r\n" \
+                                    "different value 0x00000000). Now I realize that 0x12345678 holds only one byte of a word and the next word \r\n" \
+                                    "The logic for your memcpy is correct and your interviewer didn't ask you to change it or add a restriction. \r\n" \
+                                    "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "Thank you for the demonstration. I understand now. I have come to terms with the fact that I misunderstood how \r\n" \
+                                    "memory is laid out. I thought that each individual address was capable of storing an entire word, not just a byte \r\n" \
+                                    "algorithm. Memory operates on words rather than bytes. In a 32-bit system, a word is typically 4 bytes, it\r\n"\
+                                    "akes the same amount of time to read/write 1 byte as it does to read/write 1 word. The second loop is to   \r\n"\
+                                    "Hello world Copy the logical and implementation_tsmc28hpm directories in to the Skadi home directory\r\n"\
+                                    "1.pick what kind of geek you want to be there are different kinds of geeks such as sci fi and fantasy geek\r\n"\
+                                    "#book geek manga geek and many more just be who you really are\r\n"\
+                                    "2. Read lots of books. Some good geeky books include The Lord Of The Rings, Harry Potter, The Hunger Games,\r\n"\
+                                    "I Robot and The Zombie Survival Guide. These can be found in your local library.\r\n"\
+                                    "3.Be smart. Try to get an A in every subject except for PE.\r\n"\
+                                    "4.Read geeky comics and graphic novels. You don't have to read superhero comics if you want to be geeky.\r\n"\
+                                    "You can read Science Fiction, Fantasy, Horror or Comedy.\r\n"\
+                                    "5.Watch geeky movies such as Shaun of The Dead, Star Trek, Doctor who, Revenge Of the Nerds, and Star Wars.\r\n"\
+                                    "6.Know all things Star Trek. Captain Kirk's background, the fact that spock is a vulcan, and the vulcan salute are all things that a geek must know\r\n"\
+                                    "7.Watch geeky series such as Doctor Who, Merlin and The Big Bang Theory.\r\n"\
+                                    "8.Be good with computers. Learn a programming language and read books about computers.\r\n"\
+                                    "9.Have geeky friends and a geeky hangout such as the book shop, the tabletop game shop, the comic shop and the computer shop.\r\n"\
+                                    "10.A geek knows everything\"thinkgeek.com\". Thinkgeek is a website which holds everything a geek could want. A geek has an account on thinkgeek and has thinkgeek points.\r\n"\
+                                    "11.A GEEK DOES NOT PLAY ROCK PAPER SCISSORS. A geek plays the famous game invented by Sheldon Cooper: rock-paper-scissors-lizard-Spock.\r\n"\
+                                    "12.Buy some shirts from thinkgeek.com and wear Adidas slides.\r\n";
+                        
+                                    
+int src_int[1786];              
+
+
+    
+#if test_attach
+
+        
+    pc.printf("start to test mehtod attach function now!\r\n");
+        
+    char src2[] = "this  is for test_attach test";
+    wait(2);                
+    size_t size = sizeof (src2);
+    char *dst1  = (char *) malloc(size);
+    memset (dst1, '\0', size);
+    
+    mynumber1.num = 3;  
+    DMA dma1 (-1); // choose whichever free channel
+    dma1.source (src2,1, 8); // set source as incremental. Not need to set the transfer width as MBED dma will do it for you.
+    dma1.destination (dst1, 1, 8);
+    dma1.attach_TC(test_mynumber);
+    
+      
+    dma1.start(size);
+    dma1.wait();
+    pc.printf("finish");
+    
+#endif
+    
+#if test_m2m
+    /* test the DMA M2M, copy data from src to dest, and then print out the dest mem data */
+
+    pc.printf("start to test DMA M2M test now!\r\n");   
+     // wait(1);                
+    size_t size = sizeof(src);
+    char *dst1  = (char *) malloc(size);
+        
+    char *dst2  = (char *) malloc(size);
+    memset(dst1, '\0', size+1);
+    memset(dst2, '\0', size+1);
+    t.start();
+    memcpy(dst1,src,size);
+    t.stop();
+    printf("The source size is %d\r\n", size);
+    printf("The time CPU took was %f seconds\r\n", t.read());
+    t.reset();
+
+        
+    DMA dma1(-1); // choose whichever free channel
+    dma1.source(src,1, 8); // set source as incremental. Not need to set the transfer width as MBED dma will do it for you.
+    dma1.destination(dst2, 1, 8);
+    
+    dma1.attach_TC(led_switchon_m2m);
+    dma1.attach_Err(IRQ_err);
+    t.start();
+    dma1.start(size);
+    dma1.wait();
+    t.stop();
+        
+    pc.printf("The time DMA took was %f seconds\r\n", t.read());
+    wait(5);
+    pc.printf("dst text: %s \r\n", dst2);
+    t.reset();
+    if (strcmp(dst2, dst1) != 0)
+    {
+        pc.printf("error! \r\n");
+        for (int i = 0; i < size +1; i++)
+            if(dst1[i] != dst2[i])
+                printf ("In the %d charator, dst1 is %c and dst2 is %c \r\n", i+1, dst1[i], dst2[i]);
+    }
+    else
+        pc.printf("correct! \r\n");
+#endif
+
+#if test_m2m_int
+    pc.printf("start to test DMA M2M test now!\r\n");
+    // wait(1);     
+    for (int i = 0; i < sizeof(src_int)/4; i++)
+    src_int[i]=i; 
+    size_t size = sizeof(src_int)/4;
+    int *dst1  = (int *) malloc(sizeof(src_int)/4);
+    int *dst2  = (int *) malloc(sizeof(src_int)/4);
+    memset(dst1, '\0', size);
+    memset(dst2, '\0', size);
+    t.start();
+    memcpy(dst1,src_int,size);
+    t.stop();
+    printf("The source size is %d\r\n", size);
+    printf("The time CPU took was %f seconds\r\n", t.read());
+    t.reset();
+
+        
+    DMA dma1(1); // choose whichever free channel
+    dma1.source(src_int,1); // set source as incremental. Not need to set the transfer width as MBED dma will do it for you.
+    dma1.destination(dst2, 1);
+    
+ // dma1.attach_TC(led_switchon_m2m);
+//  dma1.attach_Err(IRQ_err);
+    t.start();
+    dma1.start(size);
+    dma1.wait();
+    t.stop();
+        
+    pc.printf("The time DMA took was %f seconds\r\n", t.read());
+    wait(5);
+    for (int i=0; i<sizeof(src_int)/4;i++)
+    pc.printf("dst text: %d \r\n", dst2[i]);
+    t.reset();
+    if (memcmp(dst2, src_int, sizeof(src_int)/4) != 0)
+        pc.printf("error! \r\n");
+    else
+        pc.printf("correct! \r\n");     
+#endif      
+        
+#if test_LLI
+        
+    pc.printf ("start to test LLI now\r\n");
+
+    wait(2);
+    
+    char src_dma[] = "This is to test the scatter-gather support \r\n";
+    char src_LLI[] = "this is from linked item \r\n";
+    LPC_UART0->FCR  |=  1<<3 ; //Enable UART DMA mode
+    LPC_UART0->LCR &= ~(1<<3); // No parity bit generated 
+        
+    DMA dmaLLI(2);
+    dmaLLI.destination(&(LPC_UART0->THR),0, sizeof(char)*8);    
+    dmaLLI.source(src_dma,1, sizeof(char)*8);
+    dmaLLI.TriggerDestination(_UART0_TX);
+    dmaLLI.attach_TC(led_switchon_m2p);//  m2p_finishFlag will be set when FINISH interrupt generated
+    dmaLLI.attach_Err(IRQ_err);
+
+    dmaLLI.next((uint32_t)src_LLI, (uint32_t)&(LPC_UART0->THR), sizeof(src_LLI));
+    // dmaLLI.next((uint32_t)src_LLI, (uint32_t)dst_LLI, 7);
+    //  DMA dmaLLI2(3);
+    //  dmaLLI2.next((uint32_t)src_LLI, (uint32_t)dst_LLI, 7);
+    dmaLLI.start(sizeof(src_dma));
+    dmaLLI.wait();
+    while(1);
+#endif  
+        
+        
+        
+#if test_m2p
+    /*Test m2P, send the memory data to UART;*/ 
+    pc.printf ("start to test m2p now\r\n");
+        
+    t.start();  
+    pc.printf(src);
+    t.stop();
+    wait(1);
+    printf("The time CPU took was %f seconds\r\n", t.read());
+    wait(1);
+    t.reset();
+            
+    LPC_UART0->FCR  |=  1<<3 ; //Enable UART DMA mode
+    LPC_UART0->LCR &= ~(1<<3); // No parity bit genrated 
+        
+    DMA dma2(2);
+    dma2.destination(&(LPC_UART0->THR),0, sizeof(char)*8);
+    dma2.source(src,1, sizeof(char)*8);
+    dma2.TriggerDestination(_UART0_TX);
+    dma2.attach_TC(led_switchon_m2p);//  m2p_finishFlag will be set when FINISH interrupt generated
+    dma2.attach_Err (IRQ_err);
+    
+    t.start();
+    dma2.start(sizeof(src));
+    dma2.wait();
+    t.stop();
+    printf("The time DMA took was %f seconds\r\n", t.read());
+    printf("The transfer size is %d \r\n", sizeof(src));
+    wait(2);
+        
+    pc.printf ("Now demonstrate CPU and DMA could work together\r\n");
+    wait(1);
+    m2p_finishFlag = 0;
+    dma2.start(sizeof(src));
+    // Demonstrate CPU and DMA could work together, led2 keep blinking while DMA is transferring data 
+    
+    while (!m2p_finishFlag){
+        myled2 = !myled2;
+        wait (0.2);
+    }
+
+
+    // Demonstrate Err interrupt callback also works
+    // Dedicately read data from the unallocated memory range to generate error 
+    wait (1);
+    pc.printf ("Now demonstrate error interrupt callback also works\r\n");
+    wait(2);
+    dma2.attach_Err (IRQ_err);
+    dma2.start((sizeof(src)+4)); 
+    dma2.wait();
+        
+#endif
+
+#if test_p2m
+    
+    pc.printf("start to test DMA P2M now!\r\n");
+    wait(2);
+    volatile unsigned int data = 0;
+    unsigned int data2 = 0;
+    volatile int *dst3  = (int *) malloc(4);
+    old_ADC_init();
+
+    NVIC_DisableIRQ(ADC_IRQn); // If ADC DMA is used, the ADC interrupt must be disabled    
+    
+    DMA dma3(3);
+    dma3.destination(dst3, 0, 32); // Some sample codes show it should be half-word as only low 16bit contains the data. 
+                                                                //  But I think it should be 32 as the reigster is 32-bit width 
+    dma3.source(&(LPC_ADC->ADDR4),0, 32);
+    dma3.TriggerSource(_ADC);
+    dma3.attach_TC(led_switchon_p2m);
+        
+    while (1)
+    {
+      //  LPC_ADC->ADCR |= 1 << 24;// start the conversion now
+        dma3.start(1);
+        data= float(dst3[0]>>4 & 0xfff); // Only bit4-bit16 contains the valid ADC data
+        data2 = ADC_read(4); // read ADC channel 4
+        pc.printf("The ADC data of DMA is: %d\r\n", data);
+        pc.printf("The ADC data of CPU is: %d\r\n", data2);
+        wait (1);
+    }
+            
+    pc.printf("\nFinish!\r\n");
+#endif
+    
+
+        
+        
+#if test_p2p
+    
+    wait(2);
+    volatile unsigned int data = 0;
+    unsigned int data2 = 0;
+    volatile unsigned int  raw_data = 0; 
+    volatile int *dst3  = (int *) malloc(4);
+    old_ADC_init();
+    NVIC_DisableIRQ(ADC_IRQn); // If ADC DMA is used, the ADC interrupt must be disabled    
+    
+    LPC_UART0->FCR  |=  1<<3 ; //Enable UART DMA mode
+    LPC_UART0->LCR &= ~(1<<3); // No parity bit genrated 
+    
+    DMA dma4(4);
+    dma4.source(&(LPC_ADC->ADDR4),0, 32);
+    dma4.destination(&(LPC_UART0->THR),0,8); 
+   // dma4.destination(dst3, 0, 32);        
+    dma4.TriggerSource(_ADC);
+    dma4.TriggerDestination(_UART0_TX);
+    dma4.attach_TC(led_switchon_p2p);
+
+    while (1)
+    {
+        LPC_ADC->ADCR |= 1 << 24;// start the conversion now
+        dma4.start(1);
+    
+    /*      
+            data= float(dst3[0]>>4 & 0xfff); // Only bit4-bit16 contains the valid ADC data
+              raw_data= (unsigned int )dst3[0] &0x7fffffff;
+              pc.printf("The ADC data of raw data is: %d\r\n", raw_data);
+              pc.printf("The ADC data of DMA is: %d\r\n", data);
+        */  
+          wait (3);
+    }
+            
+
+    pc.printf("\nFinish!\r\n");
+#endif
+        
+        
+
+
+#if test_all
+        
+    DMA dma1 (1) ; 
+    DMA dma2 (2);
+    DMA dma3 (3);
+        
+    size_t size1 = sizeof (src);
+    char *dst1  = (char *) malloc(size1);
+    dma1.source (src,1); // set source as incremental. Not need to set the transfer width as MBED dma will do it for you.
+    dma1.destination (dst1, 1);
+    dma1.attach_TC(led_switchon_m2m) ;
+    dma1.attach_Err (IRQ_err);
+    
+
+
+   // char src2[] = "This message was transmitted via UART DMA from memor";
+        
+    size_t size2 = sizeof (src);
+    pc.printf("the size is %d",size2);
+    wait(1);
+    LPC_UART0->FCR  |=  1<<3 ; //Enable UART DMA mode
+    LPC_UART0->LCR &= ~(1<<3); // No parity bit genrated 
+    dma2.destination(&(LPC_UART0->THR),0, sizeof(char)*8);
+    dma2.source(src,1, sizeof(char)*8);
+    dma2.TriggerDestination(_UART0_TX);
+    dma2.attach_TC(led_switchon_m2p);//  m2p_finishFlag will be set when FINISH interrupt generated
+    dma2.attach_Err (IRQ_err);
+
+ 
+    volatile unsigned int data = 0;
+    volatile int *dst3  = (int *) malloc(128);
+    ADC_init();
+    NVIC_DisableIRQ(ADC_IRQn); // If ADC DMA is used, the ADC interrupt must be disabled    
+    dma3.destination(dst3, 1, 32); // Some sample codes show it should be half-word as only low 16bit contains the data. 
+                                                                //  But I think it should be 32 as the reigster is 32-bit width 
+    dma3.source(&(LPC_ADC->ADDR0),0, 32);
+    dma3.TriggerSource(_ADC);
+    dma3.attach_TC(led_switchon_p2m);
+    dma3.attach_Err (IRQ_err);
+  
+
+    dma1.start(size1);
+    dma2.start(size2);
+    dma3.start(32);
+
+#endif
+
+    while (1);
+    return 0;
+}
+
+
+void ADC_init()
+{
+   // ensure power is turned on
+    LPC_SC->PCONP |= (1 << 12);
+    
+    // set PCLK of ADC to 1
+    LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
+    LPC_SC->PCLKSEL0 |= 1<<24;
+    
+    // select PIN 14, ADC 0.0
+    LPC_PINCON->PINSEL1 &= (uint32_t) ~(0x3 << 14);
+    LPC_PINCON->PINSEL1 |= 0x1 << 14;
+    
+    // PIN14 no pull-up, no pull-down 
+    LPC_PINCON->PINMODE2 |= 0x2 << 28;
+    
+    // ADC conversion not start yet
+    LPC_ADC->ADCR &= ~ (1 << 24);
+    
+    // the global DONE flat in ADDR must be disabled to generate an interrupt 
+    LPC_ADC->ADINTEN &= ~(1<<8); 
+    LPC_ADC->ADINTEN = 0x1;
+     
+    LPC_ADC->ADCR = (uint32_t)  ((1 << 21)  // ADC is operational  
+                                  | (1 << 8) // APB clock is divided by 1
+                                  | 0x01); // Select AD0.0 to be sampled and converted 
+    
+
+     LPC_ADC->ADCR |= 1 << 16 ; // BURST mode
+
+}
+    
+void led_switchon_m2m(void)
+{
+    myled1=1;
+}
+
+void led_switchon_m2p(void)
+{
+    m2p_finishFlag = 1;
+    myled2=1;
+}
+
+void led_switchon_p2m(void)
+{
+    myled3=1;
+}
+
+void led_switchon_p2p(void)
+{
+    myled4=1;
+}
+
+void IRQ_err (void)
+{
+    t.stop();
+    pc.printf("The time DMA took was %f seconds\r\n", t.read());
+    myled1 = 0;
+    myled2 = 0;
+    myled3 = 0;
+    myled4 = 0;
+    wait (0.5);   
+    pc.printf ("\r\n");
+    pc.printf ("Error Interrupt happens\r\n");
+}
+
+
+static inline int div_round_up(int x, int y)
+{
+    return (x + (y - 1)) / y;
+}
+void old_ADC_init()
+{
+    // ensure power is turned on
+    LPC_SC->PCONP |= (1 << 12);
+
+    /* p19 pin is set to ADC input.*/
+    LPC_PINCON->PINSEL3 |= 0x30000000;
+    /* no pull-up, no pull-down */
+    LPC_PINCON->PINMODE3 |= 0x20000000;
+
+    // set PCLK of ADC to 1
+    LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
+    LPC_SC->PCLKSEL0 |= (0x1 << 24);
+    uint32_t PCLK = SystemCoreClock;
+
+    // calculate minimum clock divider
+    // clkdiv = divider - 1
+    uint32_t MAX_ADC_CLK = 13000000;
+    uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1;
+    
+      
+     LPC_ADC->ADCR &=  ~(1 << 0) // SEL: 0 = no channels selected  
+                       & ~ (1 << 16) // No BURST mode
+                       & ~(1 << 17)     // CLKS: not applicable
+                       & ~(1 << 24); // ADC conversion not start yet
+                                            
+        
+    LPC_ADC->ADINTEN = 1 <<8; 
+    // Set the generic software-controlled ADC settings
+    LPC_ADC->ADCR |= ( 24 << 8) // CLKDIV: PCLK max ~= 25MHz, /25 to give safe 1MHz at fastest         
+                     | (1 << 21) ; // PDN: 1 = operational
+   
+
+    // Select the  channel 4 
+    LPC_ADC->ADCR |= 1 << 4;
+    // Start conversionf
+    LPC_ADC->ADCR |= 1 << 24;
+}
+
+void burst_ADC_init()
+{
+    // ensure power is turned on
+    LPC_SC->PCONP |= (1 << 12);
+
+    /* p19 pin is set to ADC input.*/
+    LPC_PINCON->PINSEL3 |= 0x30000000;
+    /* no pull-up, no pull-down */
+    LPC_PINCON->PINMODE3 |= 0x20000000;
+
+    // set PCLK of ADC to 1
+    LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
+    LPC_SC->PCLKSEL0 |= (0x1 << 24);
+    uint32_t PCLK = SystemCoreClock;
+
+    // calculate minimum clock divider
+    // clkdiv = divider - 1
+    uint32_t MAX_ADC_CLK = 13000000;
+    uint32_t clkdiv = div_round_up(40000, MAX_ADC_CLK) - 1;
+    
+      
+    LPC_ADC->ADCR &=  ~(1 << 0) // SEL: 0 = no channels selected  
+                      & ~(1 << 17)     // CLKS: not applicable
+                      & ~(1 << 24); // ADC conversion not start yet
+                                            
+    // ADGINTEN must be set to 0 in burst mode 
+     LPC_ADC->ADINTEN &= ~(1<<8); 
+    // Set the generic software-controlled ADC settings
+    LPC_ADC->ADCR |= (clkdiv << 8)      // CLKDIV: PCLK max ~= 25MHz, /25 to give safe 1MHz at fastest  
+                     | (1 << 16)  // Burst mode
+                     | (1 << 21) ; // PDN: 1 = operational
+   
+
+    // Select the  channel 4 
+    LPC_ADC->ADCR |= 1 << 4;
+    // Start conversion
+    LPC_ADC->ADCR |= 1 << 24;
+}
+
+
+uint32_t ADC_read(uint8_t channel)
+{
+    // Select the appropriate channel and start conversion
+    LPC_ADC->ADCR &= ~0xFF;
+    LPC_ADC->ADCR |= 1 << channel;
+    LPC_ADC->ADCR |= 1 << 24;
+    // Repeatedly get the sample data until DONE bit
+    unsigned int data;
+
+    do {
+        data = LPC_ADC->ADGDR;
+    } while ((data & ((unsigned int)1 << 31)) == 0);
+    // Stop conversion
+    LPC_ADC->ADCR &= ~(1 << 24);
+    return (data >> 4) & 0xfff; // 12 bit
+    }