A study of simple ADC and DMA and UART (CY8CKIT-044)

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

As I accumulated homework in my previous sample/study,

I wanted attack one by one.

A study of simple oscilloscope using ADC and DMA (CY8CKIT-044) version 1

So the first one I challenged was

Display ADC value into UART without using CPU (except initialization).

As you know, the result of ADC component is a binary value,

I must figure out (aka hack) a way to convert a binary value into UART readable ascii letters.

Of course if we use CPU, it's a peace of cake, but without CPU it was not.

After a few days of struggle I came up with the following trick.

(1) I limit the result value of ADC as 8bit. So it's a couple of ascii letters, such as "00" "1A", etc.

(2) I prepared a couple tables which has the upper letter and the lower letter of the value.

(3) At first I assign the beginning of the above tables into the letter to UART DMA. (DMA_ASC_H and DMA_ASC_L)

(4) Each ADC results, the value will be DMAed to the LSB of each table address variable(s). (DMA_RAW_H and DMA_RAW_L)

Note: As a register is 4 bytes structure, I needed to create a 4 bytes variable then DMA the variable word to word.

(5) Then the table address value will be DMAed to the source address of Letter to UART DMA. (DMA_H_ADR and DMA_L_ADR)

020-data-flow.JPG

The higher nibble letter table

Note: For the trick, the table is aligned to 0x100 boundary.

======================

const uint8_t ascii_h[256]

__ALIGNED(0x100u)

= {

'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',

'1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',

'2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',

'3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',

'4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',

'5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',

'6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',

'7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',

'8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',

'9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',

'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',

'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',

'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',

'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',

'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',

'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'

} ;

======================

The lower nibble letter table

Note: For the trick, the table is aligned to 0x100 boundary.

======================

const uint8_t ascii_l[256]

__ALIGNED(0x100u)

= {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

} ;

======================

Note ascii_h[0xAB] = 'A' and ascii_l[0xAB] = 'B'

Schematic

Almost a Rube Goldberg machine...

012-schematic.JPG

Pins

003-pins.JPG

main.c

========================

#include "project.h"

#include "stdio.h"

#include "tty_utils.h"

#include "ascii_byte_table.h"

#define DEBUG_INFO 0

uint32_t h_char_address = (uint32_t) ascii_h ;

uint32_t l_char_address = (uint32_t) ascii_l ;

uint8_t *h_char = (uint8_t *)&h_char_address ;

uint8_t *l_char = (uint8_t *)&l_char_address ;

volatile int dma_done_flag = 0 ;

CY_ISR(dma_done_isr)

{

    dma_done_flag = 1 ;

}

void init_hardware(void)

    CyGlobalIntEnable; /* Enable global interrupts. */ 

    tty_init() ;

 

    ADC_Start() ;

 

    DMA_PRE_Start(  (void *)prefix, (void *)UART_TX_FIFO_WR_PTR) ;

    DMA_ASC_H_Start((void *)h_char, (void *)UART_TX_FIFO_WR_PTR) ;

    DMA_ASC_L_Start((void *)l_char, (void *)UART_TX_FIFO_WR_PTR) ;

    DMA_EOL_Start(  (void *)eol,    (void *)UART_TX_FIFO_WR_PTR) ;

    DMA_H_ADR_Start((void *)h_char, (void *)(&CYDMA_DESCR_BASE.descriptor[DMA_ASC_H_CHANNEL][0].src)) ;

    DMA_L_ADR_Start((void *)l_char, (void *)(&CYDMA_DESCR_BASE.descriptor[DMA_ASC_L_CHANNEL][0].src)) ;

    DMA_RAW_H_Start((void *)ADC_SAR_CHAN0_RESULT_PTR, (void *)h_char) ;

    DMA_RAW_L_Start((void *)ADC_SAR_CHAN0_RESULT_PTR, (void *)l_char) ;

 

    dma_done_int_ClearPending() ;

    dma_done_int_StartEx(dma_done_isr) ;

}

void dump_dma_ch(int ch)

{

    snprintf(str, STR_BUF_LEN, "DMA%d\n\r", ch) ;

    print(str) ;

    print("descriptor 0 :") ;

    snprintf(str, STR_BUF_LEN, "0x%08X -> 0x%08X CTRL:0x%08X Status:0x%08X\n\r",

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].src,

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].dst,

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].ctl,

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][0].status

    ) ;

    print(str) ;

    print("descriptor 1 :") ;

    snprintf(str, STR_BUF_LEN, "0x%08X -> 0x%08X CTRL:0x%08X Status:0x%08X\n\r",

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].src,

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].dst,

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].ctl,

        (uint32_t)CYDMA_DESCR_BASE.descriptor[ch][1].status

    ) ;

    print(str) ;

}

void dump_dma(void)

{

    print("DMA_RAW_H:  ") ;

    dump_dma_ch(DMA_RAW_H_CHANNEL) ;

    print("DMA_RAW_L:  ") ;

    dump_dma_ch(DMA_RAW_L_CHANNEL) ;

    print("DMA_H_ADR: ") ;

    dump_dma_ch(DMA_H_ADR_CHANNEL) ;

    print("DMA_L_ADR: ") ;

    dump_dma_ch(DMA_L_ADR_CHANNEL) ; 

    print("DMA_ASC_H:  ") ; 

    dump_dma_ch(DMA_ASC_H_CHANNEL) ;

    print("DMA_ASC_L:  ") ; 

    dump_dma_ch(DMA_ASC_L_CHANNEL) ;

    print("DMA_PRE:    ") ;

    dump_dma_ch(DMA_PRE_CHANNEL) ;

    print("DMA_EOL:    ") ; 

    dump_dma_ch(DMA_EOL_CHANNEL) ;

    print("DMA_ASC_LF:  ") ; 

    snprintf(str, STR_BUF_LEN, "h_char: 0x%08X l_char: 0x%08X\n\r",

        h_char_address, l_char_address) ;

    print(str) ;

    print("\n\r") ;

}

int main(void)

    init_hardware() ;

 

    splash("ADC-DMAx2 Test") ;

    print("\n\r") ;

 

    Timer_Start() ;

     

    for(;;)

    {

    }

}

========================

Tera Term log

010-TeraTerm-log.JPG

moto

P.S. Diagram for data flow added 25-Oct-2020

5 Replies
Kenshow
Level 8
Level 8
Distributor - Marubun (Japan)
50 solutions authored 25 solutions authored 10 solutions authored

Hi Moto-san,

I think you can reduce the number of DMA channels as follows.

1.png

Regards,

Kenshow

MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Dear Kenshow-san,

Thank you very much for your suggestion!

BTW, I wonder if we can transfer nibble to nibble by using DMA.

0xAB is 8bit (= 1 byte)

0xA is 4bit (= 1 nibble)

So, I'm afraid that we can not add 0xA to 0x150 to create 0x15A.

I will think if we can do something like that.

Best Regards,

30-Oct-2020

Motoo Tanaka

0 Likes
Kenshow
Level 8
Level 8
Distributor - Marubun (Japan)
50 solutions authored 25 solutions authored 10 solutions authored

Dear Motoo-san,

Okey, we should consider using bitband aliases. Please refer to the following web.

ビットバンド | APS|半導体技術コンテンツ・メディア  (I'm sorry in Japanese)

Best Regards,

Kenshow

MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Dear Kenshow-san,

That is a good information!

If we can use this feature, the character table can be only 16 bytes.

....

As we talked over chat, the only drawback was neither PSoC4 nor PSoC 6 (63) supports this feature...

Well, let's not worry!

It's Friday!

Best Regards,

30-Oct-2020

Motoo "Trick or Retreat!" Tanaka

Kenshow
Level 8
Level 8
Distributor - Marubun (Japan)
50 solutions authored 25 solutions authored 10 solutions authored

Dear Motoo-san,

 It was very disappointing that my idea could not be realized.

 I think you can leave the 256-byte table as it is and reduce the DMA channels. I modified the figure a little. Please refer to it in the future.

 1.png

Best Regards,

Kenshow