Manual

LCD component

LCD component

The LCD component is used to drive a single graphics LCD module up to 800 * 600 pixels with pixel clocks of up to 25MHz.

Features

  • Standard component to support different LCD displays with an RGB interface.
  • Different color depths 32 bpp, 16 bpp, etc. based on user configuration.
  • Resolution of up to 800 * 600 pixels.
  • Outputs to a CMOS interface.
  • Configurability of
    * LCD pixel dimensions,
    * clock rate,
    * horizontal and vertical timing requirements,
    * port mapping of the LCD.
  • Requires a single core for the server.
    * The function lcd_server requires just one core, the client functions, located in lcd.h are very low overhead and are called from the application.

Memory requirements

Resource

Usage

Stack

92 bytes

Program

2168 bytes

Resource requirements

Resource

Usage

Channels

1

Timers

0

Clocks

1

Logical Cores

1

Performance

The achievable effective bandwidth varies according to the available xCORE MIPS. The maximum pixel clock supported is 25MHz.

Touch screen component

The touch screen component is used to read the touch coordinates from the touch screen controller AD7879-1.

Features

  • Standard components to support touch screen controller with I2C serial interface
  • Supports 4-wire resistive touch screens of different sizes
  • Resolution of 4096 * 4096 points
  • Pen-down interrupt signal supported
  • Outputs touch coordinates
  • module_touch_controller_lib requires a single core while module_touch_controller_server requires an additional core for the server.

Memory requirements

app_touch_controller_lib_demo

Resource

Usage

Stack

304 bytes

Program

3160 bytes

app_touch_controller_server_demo

Resource

Usage

Stack

420 bytes

Program

3576 bytes

Resource requirements

app_touch_controller_lib_demo

Resource

Usage

Channels

0

Timers

3

Clocks

1

Logical Cores

1

app_touch_controller_server_demo

Resource

Usage

Channels

1

Timers

3

Clocks

1

Logical Cores

2

sliceKIT

This module may be evaluated using the sliceKIT Modular Development Platform, available from digikey. Required board SKUs are:

  • XP-SKC-L2 (sliceKIT L16 Core Board) plus XA-SK-SCR480 plus XA-SK-XTAG2 (sliceKIT XTAG adaptor)

Demonstration applications

LCD Demo Application

The LCD demo application shows how a buffer of image data can be written to the 480×272 LCD screen that is supplied with the XA-SK-SCR480 Slice Card.

  • Package: sc_lcd
  • Application: app_lcd_demo

Touch screen demo application

The touch screen demo application shows how a touch event is processed and the touch coordinates are fetched from the touch screen controller chip fitted on the XA-SK-SCR480 Slice Card.

  • Package: sc_lcd
  • Applications: app_touch_controller_lib_demo

Display controller application

This combination demo employs the module_lcd along with the module_sdram and the module_display_controller framebuffer framework component to implement a 480×272 display controller.

Required board SKUs for this demo are:

  • XP-SKC-L2 (sliceKIT L16 Core Board) plus XA-SK-XTAG2 (sliceKIT XTAG adaptor)
  • XA-SK-SCR480 for the LCD
  • XA-SK-SDRAM for the SDRAM
  • Package: sw_display_controller
  • Application: app_display_controller

The component sc_lcd includes the modules module_lcd, module_text_display and module_touch_controller_lib.

module_lcd

Configuration defines

The module_lcd includes device support defines, each support header, located in the devices directory defines a number of parameters. It is sufficient for the user to specify which device to support in the lcd_conf.h for the device to be correctly supported. To do this lcd_conf.h must include the define:
::
#define LCD_PART_NUMBER p

where p is the part the user requires support for. lcd_conf.h must be located in the application project and not the module. Currently, support is provided for:
  • AT043TN24V7
  • K430WQAV4F
  • K70DWN0V1F

Implementation specific defines

It is possible to override the default defines when a part number is selected. The defines available are:

LCD_WIDTH

This define is used to represent the width of the LCD panel in pixels.

LCD_HEIGHT

This define is used to represent the height of the LCD panel in pixels.

LCD_BITS_PER_PIXEL

Count of bits used to set a pixels RGB value, i.e. if the screen was wired for rgb565 then the LCD_BITS_PER_PIXEL would be 16, rgb888 would be 24. This is independant of the actual bit depth of the lcd.

LCD_HOR_FRONT_PORCH

The horizontal front porch timing requirement given in pixel clocks.

LCD_HOR_BACK_PORCH

The horizontal back porch timing requirement given in pixel clocks.

LCD_VERT_FRONT_PORCH

The vertical front porch timing requirement given in horizontal time periods.

LCD_VERT_BACK_PORCH

The vertical back porch timing requirement given in horizontal time periods.

LCD_HOR_PULSE_WIDTH

The horizontal pulse width timing requirement given in pixel clocks. This is the duration that the hsync signal should go low to denote the start of the horizontal frame. Set to 0 when hsync is not necessary.

LCD_VERT_PULSE_WIDTH

The vertical pulse width timing requirement given in vertical time periods. This is the duration that the vsync signal should go low to denote the start of the vertical frame. Set to 0 when vsync is not necessary.

LCD_FREQ_DIVIDEND

The defines FREQ_DIVIDEND and FREQ_DIVISOR are used to calculate the frequency of the clock used for LCD. The frequency configured = (FREQ_DIVIDEND / FREQ_DIVISOR) in MHz

LCD_FREQ_DIVISOR

The defines FREQ_DIVIDEND and FREQ_DIVISOR are used to calculate the frequency of the clock used for LCD. The frequency configured = (FREQ_DIVIDEND / FREQ_DIVISOR) in MHz

LCD_FAST_WRITE

The define enables a faster LCD write function, however, it produces more code. Use when a 25MHz pixel clock is required. It cannot be used with LCD_HOR_PULSE_WIDTH > 0 or LCD_VERT_PULSE_WIDTH > 0 as horizontal and veritcal sync signals are not supported in LCD_FAST_WRITE mode.

API

The LCD display module functionality is defined in
  • lcd.xc
  • lcd.h
  • lcd_defines.h
  • lcd_assembly.S
  • /devices

where the following functions can be found:

  • void lcd_init(chanend c_lcd)

    LCD init function.

    This sets the lcd into a state where it is ready to accept data.

    Parameters

    • c_lcd

      The channel end connecting to the lcd server.

  • static void lcd_req(chanend c_lcd)

    Receives the request for data from the LCD server.

    Parameters

    • c_lcd

      The channel end connecting to the lcd server.

  • static void lcd_update(chanend c_lcd, unsigned buffer[])

    LCD update function.

    This sends a buffer of data to the lcd server to to sent to the lcd.

    Note, no array bounds checking is performed.

    Parameters

    • c_lcd

      The channel end connecting to the lcd server.

    • buffer[]

      The data to be emitted to the lcd screen, stored in rgb565.

  • static void lcd_update_p(chanend c_lcd, unsigned buffer)

    C interface for LCD update function.

    This sends a buffer of data to the lcd server to to sent to the lcd.

    Note, no array bounds checking is performed.

    Parameters

    • c_lcd

      The channel end connecting to the lcd server.

    • buffer

      A pointer to data to be emitted to the lcd screen, stored in rgb565.

  • void lcd_server(chanend c_client, lcd_ports &ports)

    The LCD server thread.

    Parameters

    • c_client

      The channel end connecting to the client.

    • ports

      The structure carrying the LCD port details.

module_touch_controller_lib

The device-specific configuration defines and user defines are listed in touch_lib_conf.h.

Configuration defines

TOUCH_LIB_LCD_WIDTH

This define is used to represent the width of the LCD panel in pixels.

TOUCH_LIB_LCD_HEIGHT

This define is used to represent the height of the LCD panel in pixels.

TOUCH_LIB_TS_WIDTH

This define is used to represent the width of the touch screen in points.

TOUCH_LIB_TS_HEIGHT

This define is used to represent the height of the touch screen in points.

API

The touch screen module functionality is defined in
  • touch_controller_lib.xc
  • touch_controller_lib.h
  • /AD7879-1

where the following functions can be found:

  • void touch_lib_init(touch_controller_ports &ports)

    The touch controller initialisation.

    Parameters

    • ports

      The structure containing the touch controller port details.

  • void touch_lib_get_touch_coords(touch_controller_ports &ports, unsigned &x, unsigned &y)

    Get the current touch coordinates from the touch controller.

    The returned coordinates are not scaled.

    Parameters

    • ports

      The structure containing the touch controller port details.

    • x

      The X coordinate of point of touch.

    • y

      The Y coordinate of point of touch.

  • select touch_lib_touch_event(touch_controller_ports &ports)

    A select function that will wait until the touch controller reports a touch event.

    Parameters

    • ports

      The structure containing the touch controller port details.

  • void touch_lib_get_next_coord(touch_controller_ports &ports, unsigned &x, unsigned &y)

    This function will block until the controller reports a touch event at which point it will return the coordinates of that event.

    The coordinates are not scaled.

    Parameters

    • ports

      The structure containing the touch controller port details.

    • x

      The X coordinate of point of touch.

    • y

      The Y coordinate of point of touch.

  • void touch_lib_scale_coords(unsigned &x, unsigned &y)

    The function to scale coordinate values (from the touch point coordinates to the LCD pixel coordinates).

    Parameters

    • x

      The scaled X coordinate value

    • y

      The scaled Y coordinate value

This section provides information on how to program applications using the LCD module.

Source code structure

Project structure

Project

File

Description

module_lcd

lcd.h

Header file containing the APIs for the LCD component

 

lcd.xc

File containing the implementation of the LCD component

 

lcd_defines.xc

Header file containing the user configurable defines for the LCD

 

lcd_assembly.S

Assembly file containing the fast_write functionality for the LCD.

 

/devices

Folder containing header files of configurations for LCDs

Additional files

Additional files

File name

Description

generate.pl

Perl file for generating a fast write function body for LCD screens of arbitrary width.

How to select the LCD target

The module has been designed to support multiple LCD targets. Each target has a specific configuration and have been provided
with the component int the /devices directory. The module only supports a single LCD target per xCORE.

To select the target the following should be done:

If the required target is the part AT043TN24V7 LCD display then,
  • Create a header in the application project called lcd_conf.h
  • In the lcd_conf.h add the define #define LCD_PART_NUMBER AT043TN24V7. This will include the “lcd_defines_AT043TN24V7.h” required for the selected target.
  • Any specific overrides should be added to the lcd_conf.h. For example, to override the LCD_HEIGHT to 600 pixels add the line #define LCD_HEIGHT 600.
  • The application should also include the port mapping for the LCD as per the hardware used. A variable of the type structure lcd_ports should be created and must include the port information

Example:
In the application file

struct lcd_ports lcd_ports = {
        XS1_PORT_1G,
        XS1_PORT_1F,
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1C,
        XS1_CLKBLK_1
};

The declared variable lcd_ports is used by the LCD server call to address these ports. A core should have the lcd_server running on it and it should be connected by a channel to the application, for example:

chan c_lcd;
par {
      lcd_server(c_lcd, lcd_ports);
      application(c_lcd);
}

Executing the project

The module by itself cannot be built or executed separately. It must be linked in to an application which needs LCD display. Once the module is linked to the application, the application can be built and tested for driving a LCD screen.

The following should be done in order to link the component to the application project
  1. The module name module_lcd should be added to the list of MODULES in the application project build options.
  2. Now the module is linked to the application and can be directly used

Software requirements

The module is built on XDE Tool version 12.0
The module can be used in version 12.0 or any higher version of xTIMEcomposer.

This section provides information on how to program applications using the touch controller module.

Source code structure

Project structure

Project

File

Description

module_touch_controller_lib

touch_controller_lib.h

Header file containing the APIs for interfacing touch controller component

 

touch_controller_lib.xc

File containing the implementation of APIs

 

/AD7879-1

Folder containing files for the implementation of touch controller component

 

touch_controller_impl.h

Header file containing the APIs for implementing touch controller component

 

touch_controller_impl.xc

File containing the implementation of touch controller component

module_touch_controller_server

touch_controller_server.h

Header file containing the APIs for interfacing touch controller component

 

touch_controller_server.xc

File containing the implementation of APIs

 

/AD7879-1

Folder containing files for the implementation of touch controller component

 

touch_controller_impl.h

Header file containing the APIs for implementing touch controller component

 

touch_controller_impl.xc

File containing the implementation of touch controller component

How to develop an application

The modules have been designed to support two types of interfacing with the touch screen controller; one for direct interfacing and the other for interfacing through a server. Only one of these two modules should be used by the application program.

To use a module,
  • Create a header file in the application project called touch_lib_conf.h or touch_server_conf.h.
  • In the header file, add the defines for conditional compilation and device-specific parameters.
  • The application should also include the port mapping for the touch screen controller. A variable of the type structure touch_controller_ports should be created and must include the port information.

Example:
In the application file

struct touch_controller_ports ports = {
        XS1_PORT_1E,
        XS1_PORT_1H,
        1000,
        XS1_PORT_1D
};

When module_touch_controller_server is used, a core should have the touch_controller_server running on it and it should be connected by a channel to the application, for example:

chan c;
par {
      touch_controller_server(c, ports);
      app(c);
}

Executing the project

The touch controller module by itself cannot be built or executed separately. It must be linked into an application. The application also depends on I2C module. Once the modules are linked to the application, the application can be built and run.

The following should be done in order to link the modules to the application project.
  1. The module name module_touch_controller_lib or module_touch_controller_server should be added to the list of MODULES in the application project build options.
  2. The module name module_i2c_master should also be added.
  3. Now the modules are linked to the application and can be directly used

Software requirements

The modules are built on XDE Tool version 12.0
The modules can be used in version 12.0 or any higher version of xTIMEcomposer.

This section provides information on how to program applications using the LCD module.

Source code structure

Project structure

Project

File

Description

module_lcd

lcd.h

Header file containing the APIs for the LCD component

 

lcd.xc

File containing the implementation of the LCD component

 

lcd_defines.xc

Header file containing the user configurable defines for the LCD

 

lcd_assembly.S

Assembly file containing the fast_write functionality for the LCD.

 

/devices

Folder containing header files of configurations for LCDs

Additional files

Additional files

File name

Description

generate.pl

Perl file for generating a fast write function body for LCD screens of arbitrary width.

How to select the LCD target

The module has been designed to support multiple LCD targets. Each target has a specific configuration and have been provided
with the component int the /devices directory. The module only supports a single LCD target per xCORE.

To select the target the following should be done:

If the required target is the part AT043TN24V7 LCD display then,
  • Create a header in the application project called lcd_conf.h
  • In the lcd_conf.h add the define #define LCD_PART_NUMBER AT043TN24V7. This will include the “lcd_defines_AT043TN24V7.h” required for the selected target.
  • Any specific overrides should be added to the lcd_conf.h. For example, to override the LCD_HEIGHT to 600 pixels add the line #define LCD_HEIGHT 600.
  • The application should also include the port mapping for the LCD as per the hardware used. A variable of the type structure lcd_ports should be created and must include the port information

Example:
In the application file

struct lcd_ports lcd_ports = {
        XS1_PORT_1G,
        XS1_PORT_1F,
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1C,
        XS1_CLKBLK_1
};

The declared variable lcd_ports is used by the LCD server call to address these ports. A core should have the lcd_server running on it and it should be connected by a channel to the application, for example:

chan c_lcd;
par {
      lcd_server(c_lcd, lcd_ports);
      application(c_lcd);
}

Executing the project

The module by itself cannot be built or executed separately. It must be linked in to an application which needs LCD display. Once the module is linked to the application, the application can be built and tested for driving a LCD screen.

The following should be done in order to link the component to the application project
  1. The module name module_lcd should be added to the list of MODULES in the application project build options.
  2. Now the module is linked to the application and can be directly used

Software requirements

The module is built on XDE Tool version 12.0
The module can be used in version 12.0 or any higher version of xTIMEcomposer.

This section provides information on how to program applications using the touch controller module.

Source code structure

Project structure

Project

File

Description

module_touch_controller_lib

touch_controller_lib.h

Header file containing the APIs for interfacing touch controller component

 

touch_controller_lib.xc

File containing the implementation of APIs

 

/AD7879-1

Folder containing files for the implementation of touch controller component

 

touch_controller_impl.h

Header file containing the APIs for implementing touch controller component

 

touch_controller_impl.xc

File containing the implementation of touch controller component

module_touch_controller_server

touch_controller_server.h

Header file containing the APIs for interfacing touch controller component

 

touch_controller_server.xc

File containing the implementation of APIs

 

/AD7879-1

Folder containing files for the implementation of touch controller component

 

touch_controller_impl.h

Header file containing the APIs for implementing touch controller component

 

touch_controller_impl.xc

File containing the implementation of touch controller component

How to develop an application

The modules have been designed to support two types of interfacing with the touch screen controller; one for direct interfacing and the other for interfacing through a server. Only one of these two modules should be used by the application program.

To use a module,
  • Create a header file in the application project called touch_lib_conf.h or touch_server_conf.h.
  • In the header file, add the defines for conditional compilation and device-specific parameters.
  • The application should also include the port mapping for the touch screen controller. A variable of the type structure touch_controller_ports should be created and must include the port information.

Example:
In the application file

struct touch_controller_ports ports = {
        XS1_PORT_1E,
        XS1_PORT_1H,
        1000,
        XS1_PORT_1D
};

When module_touch_controller_server is used, a core should have the touch_controller_server running on it and it should be connected by a channel to the application, for example:

chan c;
par {
      touch_controller_server(c, ports);
      app(c);
}

Executing the project

The touch controller module by itself cannot be built or executed separately. It must be linked into an application. The application also depends on I2C module. Once the modules are linked to the application, the application can be built and run.

The following should be done in order to link the modules to the application project.
  1. The module name module_touch_controller_lib or module_touch_controller_server should be added to the list of MODULES in the application project build options.
  2. The module name module_i2c_master should also be added.
  3. Now the modules are linked to the application and can be directly used

Software requirements

The modules are built on XDE Tool version 12.0
The modules can be used in version 12.0 or any higher version of xTIMEcomposer.

This tutorial describes the demo applications included in the XMOS LCD software component.
Recommended Hardware
describes the required hardware setups to run the demos.

app_lcd_demo

This application demonstrates how the module is used to write image data to the LCD screen. The purpose of this application is to show how data is passed to the lcd_server

Application notes

  1. lcd_server requires a single logical core.
  2. lcd_init must be called before lcd_update_p or lcd_update are called. This puts the LCD server into a state ready to accept data.
  3. lcd_update and lcd_update_p are used to send an array of pixel data to the LCD server. There is a real-time requirement that this function is called often enough to maintain the display. lcd_update_p is the C interface to the LCD server, it takes a pointer to an array rather than the array itself.
  4. lcd_req is a function (also a select handler) that acknowledges the LCDs request for the next line of pixel data.
  5. The LCD server does no buffering of pixel line arrays, therefore, for every lcd_req there must be only one lcd_update or lcd_update_p. Likewise for every lcd_update or lcd_update_p there must be only one lcd_req.
  6. The pixel array must be on the same tile as the lcd_server.

Getting started

  1. Plug the XA-SK-LCD Slice Card into the ‘STAR’ slot of the sliceKIT Core Board
  2. Plug the XA-SK-XTAG2 Card into the sliceKIT Core Board.
  3. Ensure the XMOS LINK switch on the XA-SK-XTAG2 is set to “off”.
  4. Ensure the jumper on the XA-SK-SCR480 is bridged if the back light is required.
  5. Open app_lcd_demo.xc and build the project.
  6. Run the program

The output produced should look like a bouncing “X” on the LCD screen.

app_touch_controller_lib_demo

This application demonstrates how the module module_touch_controller_lib is used to fetch the touch coordinates from the touch screen controller.

Application notes

  1. touch_lib_init must be called before calling touch_lib_req_next_coord or/and touch_lib_req_next_coord_timed.
  2. touch_lib_req_next_coord and touch_lib_req_next_coord_timed wait for touch event and then read the touch coordinates stored in the result registers of touch screen controller. touch_lib_req_next_coord_timed computes the time delay in touch event from the function call.

Getting started

  1. Plug the XA-SK-LCD Slice Card into the ‘TRIANGLE’ slot of the sliceKIT Core Board
  2. Plug the XA-SK-XTAG2 Card into the sliceKIT Core Board.
  3. Click on the app_touch_controller_lib_demo and build the project.
  4. Run the demo.

LCD component Read More »

SDRAM Demo Quickstart Guide

This simple demonstration of xTIMEcomposer Studio functionality uses the XA-SK-SDRAM Slice Card together with the xSOFTip module_sdram to demonstrate how the module is used to read and write to the SDRAM.

Hardware Setup

The XP-SKC-L2 Slicekit Core board has four slots with edge conectors: SQUARE, CIRCLE,“TRIANGLE“ and STAR.

To setup up the system:

  1. Connect XA-SK-SDRAM Slice Card to the XP-SKC-L2 Slicekit Core board using the connector marked with the STAR.
  2. Connect the XTAG Adapter to Slicekit Core board, and connect XTAG-2 to the adapter.
  3. Connect the XTAG-2 to host PC. Note that the USB cable is not provided with the Slicekit starter kit.
  4. Set the XMOS LINK to OFF on the XTAG Adapter.
  5. Switch on the power supply to the Slicekit Core board.
Hardware Setup for SDRAM Demo

/files/images/15929/7/hardware_setup.jpg

Import and Build the Application

  1. Open xTIMEcomposer and check that it is operating in online mode. Open the edit perspective (Window->Open Perspective->XMOS Edit).
  2. Locate the 'Slicekit SDRAM Simple Demo' item in the xSOFTip pane on the bottom left of the window and drag it into the Project Explorer window in the xTIMEcomposer. This will also cause the modules on which this application depends (in this case, module_sdram) to be imported as well.
  3. Click on the app_sdram_demo item in the Explorer pane then click on the build icon (hammer) in xTIMEcomposer. Check the console window to verify that the application has built successfully. There will be quite a number of warnings that bidirectional buffered port not supported in hardware. These can be safely ignored for this component.

For help in using xTIMEcomposer, try the xTIMEcomposer tutorial. FIXME add link.

Note that the Developer Column in the xTIMEcomposer on the right hand side of your screen provides information on the xSOFTip components you are using. Select the module_sdram component in the Project Explorer, and you will see its description together with API documentation. Having done this, click the back icon until you return to this quickstart guide within the Developer Column.

Run the Application

Now that the application has been compiled, the next step is to run it on the Slicekit Core Board using the tools to load the application over JTAG (via the XTAG2 and Xtag Adaptor card) into the xCORE multicore microcontroller.

  1. Click on the Run icon (the white arrow in the green circle). The debug console window in xTIMEcomposer should then display the message SDRAM demo complete. This has been generated from the application code via a call to the printf() function.
  2. If SDRAM demo fail is shown then check that the XMOS LINK is set to OFF then repeat.

Next Steps

Now that the demo has been run you could try and adjust the BUF_WORDS setting. Note, if you try to allocate more than 64KB of internal XCore memory then the demo will not compile as the Xcore wont be able to hold the image.

Look at the Code

  1. Examine the application code. In xTIMEcomposer navigate to the src directory under app_sdram_demo and double click on the app_sdram_demo.xc file within it. The file will open in the central editor window.
  2. Find the main function and note that it runs the application() function on a single logical core.
  3. Find the sdram_buffer_write function within application(). There are 4 SDRAM I/O commands: sdram_buffer_write, sdram_buffer_read, sdram_full_page_write, sdram_full_page_read. They must all be followed by a sdram_wait_until_idle before another I/O command may be issued. When the sdram_wait_until_idle returns then the data is now at it destination. This functionality allows the application to be getting on with something else whilst the SDRAM server is busy with the I/O.
  4. There is no need to explictly refresh the SDRAM as this is managed by the sdram_server.

Try the Benchmark and Regressession Demo

After completing this demo there are two more application to try:
  1. app_sdram_benchmark benchmarks the performance of the module. It does no correctness testing but instead tests the throughput of the SDRAM server.
  2. app_sdram_regress this demo runs a series of regression tests of increasing difficulty, beginning from using a single core for the sdram_server with one core loaded progressing to all cores being loaded to simulate an XCore under full load.

To try these repeat the procedure in “Import and Build the Application” but with either app_sdram_benchmark or app_sdram_regress.

Try Other Application Demos which use the SDRAM

There are two other siognificant application demos which utilise this component.

  • The Display Controller Demo combines the SDRAM Slice with the XA-SK-SCR480 LCD Slice Card to create a fully functioning 480×272 display controller, with the SDRAM actig as the framebuffer.
  • The Audio Reverb Demo utilises the SDRAM component to store enough audio samples to create large audio delay lines, which are a required component of various audio effects. In this case, a reverberation effect is demonstrated.

SDRAM Demo Quickstart Guide Read More »

XMOS SDRAM Component

SDRAM Controller Component

The SDRAM module is designed for 16 bit read and write access of arbitrary length at up to 50MHz clock rates. It uses an optimised pinout with address and data lines overlaid along with other pinout optimisations in order to implement 16 bit read/write with up to 13 address lines in just 20 pins.

The module currently targets the ISSI 6400 SDRAM but is easily specialised for the smaller and larger members of this family as well as single data rate SDRAM memory from other manufacturers.

SDRAM Component Features

The SDRAM component has the following features:

  • Configurability of
    • SDRAM geometry,
    • clock rate,
    • refresh properties,
    • server commands supported,
    • port mapping of the SDRAM.
  • Supports
    • buffer read,
    • buffer write,
    • full row(page) read,
    • full row(page) write,
    • refresh handled by the SDRAM component itself.
  • Requires a single core for the server.
    • The function sdram_server requires just one core, the client functions, located in sdram.h are very low overhead and are called from the application.

Memory requirements

Resource

Usage

Stack

256 bytes

Program

10272 bytes

Resource requirements

Resource

Usage

Channels

1

Timers

1

Clocks

1

Logical Cores

1

Performance

The achievable effective bandwidth varies according to the available XCore MIPS. This information has been obtained by testing on real hardware.

XCore MIPS

Cores

System Clock

Max Read (MB/s)

Max Write (MB/s)

50

8

400MHz

66.84

70.75

57

7

400MHz

68.13

71.68

66

6

400MHz

69.83

73.41

80

5

400MHz

71.68

74.99

100

4

400MHz

71.89

75.22

100

3

400MHz

71.89

75.22

100

2

400MHz

71.89

75.22

62.5

8

500MHz

66.82

70.34

83

7

500MHz

68.08

71.47

100

6

500MHz

69.83

73.19

125

5

500MHz

71.68

74.76

125

4

500MHz

71.89

74.99

125

3

500MHz

71.89

74.99

125

2

500MHz

71.89

74.99

SDRAM Memory Mapper

A memory mapper module called module_sdram_memory_mapper may be used in order to abstract the physical geometry of the SDRAM from the application. Its only function is to map the physical geometry of the SDRAM to a virtual byte addresses that the application can use.

Memory requirements

Resource

Usage

Stack

0 bytes

Program

32 bytes

Resource requirements

Resource

Usage

Channels

0

Timers

0

Clocks

0

Logical Cores

0

Slicekit

This module may be evaluated using the Slicekit Modular Development Platform, available from digikey. Required board SKUs are:

  • XP-SKC-L2 (Slicekit L2 Core Board) plus XA-SK-SDRAM plus XA-SK-XTAG2 (Slicekit XTAG adaptor)

Demonstration Applications

Testbench Application

This application serves as a software regression to aid implementing new SDRAM interfaces and verifying current ones. The demo runs a series of regression tests of increasing difficulty, beginning from using a single core for the server and a single core for the sdram_server progressing to all cores being loaded to simulate an XCore under full load.

  • Package: sc_sdram_burst
  • Application: app_sdram_regress

Benchmark Application

This application benchmarks the performance of the module. It does no correctness testing but instead tests the throughput of the SDRAM server.

  • Package: sc_sdram_burst
  • Application: app_sdram_benchmark

Demo Application

This application demonstrates how the module is used to accesses memory on the SDRAM.

  • Package: sc_sdram_burst
  • Application: app_sdram_demo

Display Controller Application

This combination demo employs this module along with the module_lcd LCD driver and the module_framebuffer framebuffer framework component to implement a 480×272 display controller.

Required board SKUs for this demo are:

  • XP-SKC-L2 (Slicekit L2 Core Board) plus XA-SK-SDRAM plus XA-SK-LCD480 plus XA-SK-XTAG2 (Slicekit XTAG adaptor)
  • Package: sw_display_controller
  • Application: app_graphics_demo

Configuration Defines

The file sdram_conf.h must be provided in the application source code, and it must define:

SDRAM_DEFAULT_IMPLEMENTATION

It can also be used to override the default values specified in

  • IMPL/sdram_config_IMPL.h
  • IMPL/sdram_geometry_IMPL.h
  • sdram_commands_IMPL.h

where IMPL is the SDRAM implementation to be overridden. These files can set the following defines:

Implementation Specific Defines

When overriding one of these defines a suffix of _IMPL needs to be added. For example, to override SDRAM_CLOCK_DIVIDER to 2 for the PINOUT_V1_IS42S16100F target add the line:

#define SDRAM_CLOCK_DIVIDER_PINOUT_V1_IS42S16100F 2

to sdram_conf.h.

SDRAM_REFRESH_MS

This specifies that during a period of SDRAM_REFRESH_MS milliseconds a total of SDRAM_REFRESH_CYCLES refresh instructions must be issued to maintain the contents of the SDRAM.

SDRAM_REFRESH_CYCLES

As above.

SDRAM_ACCEPTABLE_REFRESH_GAP

This define specifies how long the sdram_server can go between issuing bursts of refreshes. The SDRAM server issues refreshes in bursts when it is not servicing a read/write command. The number of refresh commands for a burst is automatically calculated, hence, if a read or write command is being serviced when a refresh burst should start then it will wait until the service is over then increase its burst size appropriately. If set above SDRAM_REFRESH_CYCLES then the SDRAM will fail. The default is (SDRAM_REFRESH_CYCLES/8). The unit is given in refresh periods. For example, the value would mean that the SDRAM is allowed to go SDRAM_REFRESH_MS/SDRAM_REFRESH_CYCLES*N milliseconds before refreshing. The larger the number (up to SDRAM_REFRESH_CYCLES) the smaller the constant time impact but the larger the overall impact.

SDRAM_CMDS_PER_REFRESH

This defines the minimum time between refreshes in SDRAM Clk cycles. Must be in the range from 2 to 4 inclusive.

SDRAM_EXTERNAL_MEMORY_ACCESSOR

This defines if the memory is accessed by another device(other than the XCore). If not defined then faster code will be produced.

SDRAM_CLOCK_DIVIDER

Set SDRAM_CLOCK_DIVIDER to divide down the reference clock to get the desired SDRAM Clock. The reference clock is divided by 2*SDRAM_CLOCK_DIVIDER.

SDRAM_MODE_REGISTER

This defines the configuration of the SDRAM. This is the value to be loaded into the mode register.

SDRAM Geometry Defines

These are implementation specific.

SDRAM_ROW_ADDRESS_BITS

This defines the number of row address bits.

SDRAM_COL_ADDRESS_BITS

This defines the number of column address bits.

SDRAM_BANK_ADDRESS_BITS

This defines the number of bank address bits.

SDRAM_COL_BITS

This defines the number of bits per column, i.e. the data width. This should only be changed if an SDRAM of bus width other than 16 is used.

SDRAM Commands Defines

These are non-implementation specific.

SDRAM_ENABLE_CMD_WAIT_UNTIL_IDLE

Enable/Disable the wait until idle command.

SDRAM_ENABLE_CMD_BUFFER_READ

Enable/Disable the buffer read command.

SDRAM_ENABLE_CMD_BUFFER_WRITE

Enable/Disable the buffer write command.

SDRAM_ENABLE_CMD_FULL_ROW_READ

Enable/Disable the full row read command.

SDRAM_ENABLE_CMD_FULL_ROW_WRITE

Enable/Disable the full row write command.

These defines switch commands on and off in the server and client. Set to 0 for disable, set to 1 for enable. Disabling unused commands will cause a code size decrease.

Port Config

The port config is given in \IMPL\sdram_ports_IMPL.h and is implementation specific.

SDRAM API

These are the functions that are called from the application and are included in sdram.h.

Server Functions

C and XC Interface

  • void sdram_server(chanend client, struct sdram_ports_PINOUT_V1_IS42S16400F &ports)

    The SDRAM server thread.

    Parameters

    • client

      The channel end connecting the application to the server

    • ports

      The structure carrying the SDRAM port details.

XC Interface

  • void sdram_wait_until_idle(chanend server, unsigned buffer[])

    Function to wait until the SDRAM server is idle and ready to accept another command.

    Parameters

    • server

      The channel end connecting the application to the server

    • buffer[]

      The buffer where the data was written or read from in the previous command.

  • void sdram_buffer_write(chanend server, unsigned bank, unsigned start_row, unsigned start_col, unsigned width_words, unsigned buffer[])

    Used to write an arbitrary sized buffer of data to the SDRAM.

    Note: no buffer overrun checking is performed.

    Parameters

    • server

      The channel end connecting the application to the server.

    • bank

      The bank number in the SDRAM into which the buffer of data should be written.

    • start_row

      The starting row number in the SDRAM into which the buffer of data should be written.

    • start_col

      The starting column number in the SDRAM into which the buffer of data should be written.

    • width_words

      The number of words to be written to the SDRAM.

    • buffer[]

      The buffer where the data will be read from.

  • void sdram_full_row_write(chanend server, unsigned bank, unsigned row, unsigned buffer[])

    Used write a full row of data from a buffer to the SDRAM.

    Note: no buffer overrun checking is performed. Full row accesses are always begin aligned to coloumn 0.

    Parameters

    • server

      The channel end connecting the application to the server

    • bank

      The bank number in the SDRAM into which the buffer of data should be written

    • row

      The row number in the SDRAM into which the buffer of data should be written.

    • buffer[]

      The buffer where the data will be read from.

  • void sdram_buffer_read(chanend server, unsigned bank, unsigned start_row, unsigned start_col, unsigned width_words, unsigned buffer[])

    Used to read to an arbitrary size buffer of data from the SDRAM.

    Note: no buffer overrun checking is performed.

    Parameters

    • server

      The channel end connecting the application to the server

    • bank

      The bank number in the SDRAM from which the SDRAM data should be read.

    • start_row

      The starting row number in the SDRAM from which the SDRAM data should be read.

    • start_col

      The starting column number in the SDRAM from which the SDRAM data should be read.

    • width_words

      The number of words to be read from the SDRAM.

    • buffer[]

      The buffer where the data will be written to.

  • void sdram_full_row_read(chanend server, unsigned bank, unsigned row, unsigned buffer[])

    Used read a full row of data from a buffer to the SDRAM.

    Note: no buffer overrun checking is performed. Full row accesses are always begin aligned to coloumn 0.

    Parameters

    • server

      The channel end connecting the application to the server.

    • bank

      The bank number in the SDRAM from which the SDRAM data should be read.

    • row

      The row number in the SDRAM from which the SDRAM data should be read.

    • buffer[]

      The buffer where the data will be written to.

C Interface

  • void sdram_wait_until_idle_p(chanend server, intptr_t buffer)

    Function to wait until the SDRAM server is idle and ready to accept another command.

    Parameters

    • server

      The channel end connecting the application to the server

    • buffer

      A pointer to the buffer where the data was written or read from in the previous command.

  • void sdram_buffer_write_p(chanend server, unsigned bank, unsigned start_row, unsigned start_col, unsigned width_words, intptr_t buffer)

    Used to write an arbitrary sized buffer of data to the SDRAM.

    Note: no buffer overrun checking is performed.

    Parameters

    • server

      The channel end connecting the application to the server.

    • bank

      The bank number in the SDRAM into which the buffer of data should be written.

    • start_row

      The starting row number in the SDRAM into which the buffer of data should be written.

    • start_col

      The starting column number in the SDRAM into which the buffer of data should be written.

    • width_words

      The number of words to be written to the SDRAM.

    • buffer[]

      The buffer where the data will be read from.

  • void sdram_full_row_write_p(chanend server, unsigned bank, unsigned row, intptr_t buffer)

    Used write a full row of data from a buffer to the SDRAM.

    Note: no buffer overrun checking is performed. Full row accesses are always begin aligned to coloumn 0.

    Parameters

    • server

      The channel end connecting the application to the server

    • bank

      The bank number in the SDRAM into which the buffer of data should be written

    • row

      The row number in the SDRAM into which the buffer of data should be written.

    • buffer

      A pointer to the buffer where the data will be read from.

  • void sdram_buffer_read_p(chanend server, unsigned bank, unsigned start_row, unsigned start_col, unsigned width_words, intptr_t buffer)

    Used to read to an arbitrary size buffer of data from the SDRAM.

    Note: no buffer overrun checking is performed.

    Parameters

    • server

      The channel end connecting the application to the server

    • bank

      The bank number in the SDRAM from which the SDRAM data should be read.

    • start_row

      The starting row number in the SDRAM from which the SDRAM data should be read.

    • start_col

      The starting column number in the SDRAM from which the SDRAM data should be read.

    • width_words

      The number of words to be read from the SDRAM.

    • buffer

      A pointer to the buffer where the data will be written to.

  • void sdram_full_row_read_p(chanend server, unsigned bank, unsigned row, intptr_t buffer)

    Used read a full row of data from a buffer to the SDRAM.

    Note: no buffer overrun checking is performed. Full row accesses are always begin aligned to coloumn 0.

    Parameters

    • server

      The channel end connecting the application to the server.

    • bank

      The bank number in the SDRAM from which the SDRAM data should be read.

    • row

      The row number in the SDRAM from which the SDRAM data should be read.

    • buffer

      A pointer to the buffer where the data will be written to.

SDRAM Memory Mapper API

These are the functions that are called from the application and are included in sdram_memory_mapper.h.

Server Functions

XC Interface

  • void mm_read_words(chanend server, unsigned address, unsigned words, unsigned buffer[])

    Reads words from the SDRAM server on the end of the channel provided.

    Parameters

    • server

      The channel end connecting to the SDRAM server.

    • address

      The virtual byte address of where the read will begin from.

    • words

      The count of words to be read

    • buffer[]

      The buffer where the data will be written to.

  • void mm_write_words(chanend server, unsigned address, unsigned words, unsigned buffer[])

    Writes words to the SDRAM server on the end of the channel provided.

    Parameters

    • server

      The channel end connecting to the SDRAM server.

    • address

      The virtual byte address of where the write will begin from.

    • words

      The count of words to be written.

    • buffer[]

      The buffer where the data will be written to.

  • void mm_wait_until_idle(chanend server, unsigned buffer[])

    Returns when the SDRAM server is in the idle state.

    Parameters

    • server

      The channel end connecting to the SDRAM server.

    • buffer[]

      The buffer which the last command was performed on.

C Interface

  • void mm_read_words_p(chanend server, unsigned address, unsigned words, intptr_t buffer)

    Reads words from the SDRAM server on the end of the channel provided.

    Parameters

    • server

      The channel end connecting to the SDRAM server.

    • address

      The virtual byte address of where the read will begin from.

    • words

      The count of words to be read

    • buffer

      A pointer to the buffer where the data will be written to.

  • void mm_write_words_p(chanend server, unsigned address, unsigned words, intptr_t buffer)

    Writes words to the SDRAM server on the end of the channel provided.

    Parameters

    • server

      The channel end connecting to the SDRAM server.

    • address

      The virtual byte address of where the write will begin from.

    • words

      The count of words to be written.

    • buffer

      A pointer to the buffer where the data will be written to.

  • void mm_wait_until_idle_p(chanend server, intptr_t buffer)

    Returns when the SDRAM server is in the idle state.

    Parameters

    • server

      The channel end connecting to the SDRAM server.

    • buffer

      A pointer to the buffer which the last command was performed on.

This section provides information on how to program applications using the SDRAM module.

SDRAM Default implementation

For convenience the module_sdram can use a default implementation. When the define SDRAM_DEFAULT_IMPLEMENTATION is set in sdram_conf.h to one of the supported targets then the sdram_server function will act as a call to the specified implementation. The same applies for the sdram_ports structure. The currently supported targets are:
  • PINOUT_V1_IS42S16400F – This corresponds to the ISSI part IS42S16400F in a 20 pin configuration.
  • PINOUT_V1_IS42S16160D – This corresponds to the ISSI part IS42S16160D in a 20 pin configuration.
  • PINOUT_V0 – This is for a legacy 22 pin configuration.

Single SDRAM Support

For a application with a single SDRAM the default implementation should be set. If it is not set then the explicit sdram_server and sdram_ports must be used. The same applied for all the implementation specific defines.

Multiple Homogeneous SDRAM Support

For a application with a single SDRAM the default implementation should be set. For example, to drive two IS42S16400F parts, set the SDRAM_DEFAULT_IMPLEMENTATION to PINOUT_V1_IS42S16400F then the following will create the servers:

chan c,d;
par {
        sdram_server(c, ports_0);
        sdram_server(d, ports_1);
        app_0(c);
        app_1(d);
}

and the ports for the above would have been created by:

struct sdram_ports ports_0 = {
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1G,
        XS1_PORT_1C,
        XS1_PORT_1F,
        XS1_CLKBLK_1
};
struct sdram_ports ports_1 = {
        XS1_PORT_16B,
        XS1_PORT_1J,
        XS1_PORT_1I,
        XS1_PORT_1K,
        XS1_PORT_1L,
        XS1_CLKBLK_1
};

Multiple Heterogeneous SDRAM Support

It is possible for the application to drive multiple heterogeneous SDRAM devices simultaneously. In this case each sdram_server and sdram_ports usage must be explicit to the implementation. For example, to drive an IS42S16400F part and an IS42S16160D part, then the following will create the servers:

chan c,d;
par {
        sdram_server_PINOUT_V1_IS42S16400F(c, ports_0);
        sdram_server_PINOUT_V1_IS42S16160D(d, ports_1);
        app_0(c);
        app_1(d);
}

and the ports for the above would have been created by:

struct sdram_ports_PINOUT_V1_IS42S16400F ports_0 = {
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1G,
        XS1_PORT_1C,
        XS1_PORT_1F,
        XS1_CLKBLK_1
};
struct sdram_ports_PINOUT_V1_IS42S16160D ports_1 = {
        XS1_PORT_16B,
        XS1_PORT_1J,
        XS1_PORT_1I,
        XS1_PORT_1K,
        XS1_PORT_1L,
        XS1_CLKBLK_1
};

Notes

The sdram_server and application must be on the same tile.

Source code structure

Directory Structure

A typical SDRAM application will have at least three top level directories. The application will be contained in a directory starting with app_, the sdram module source is in
the module_sdram directory and the directory module_xcommon contains files required to build the application.

app_[my_app_name]/
module_sdram/
module_xcommon/

Of course the application may use other modules which can also be directories at this level. Which modules are compiled into the application is controlled by the USED_MODULES define in the application Makefile.

Key Files

The following header file contains prototypes of all functions required to use use the SDRAM
module. The API is described in SDRAM API
.

Key Files

File

Description

sdram.h

SDRAM API header file

Module Usage

To use the SDRAM module first set up the directory structure as shown above. Create a file in the app folder called sdram_conf.h and into it insert a define for SDRAM_DEFAULT_IMPLEMENTATION. It should be defined as the implementation you want to use, for example for the Slicekit the following would be correct:

#define SDRAM_DEFAULT_IMPLEMENTATION PINOUT_V1_IS42S16160D

Declare the sdram_ports structure used by the sdram_server. This will look like:

struct sdram_ports sdram_ports = {
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1G,
        XS1_PORT_1C,
        XS1_PORT_1F,
        XS1_CLKBLK_1
};

Next create a main function with a par of both the sdram_server function and an application function, these will require a channel to connect them. For example:

int main() {
  chan sdram_c;
  par {
    sdram_server(sdram_c, sdram_ports);
    application(sdram_c);
  }
  return 0;
}

Now the application function is able to use the SDRAM server.

The SDRAM memory mapper has a simple interface where to the mm_read_words and mm_write_words a virtual address is passes, this virtual address is mapped to a physical address and the I/O is performed there. The mm_wait_until_idle exists so that the application can run the I/O commands in a non-blocking manner then confirm that the command has when the mm_wait_until_idle returns.

Software Requirements

The component is built on xTIMEcomposer Tools version 12.0.
The component can be used in version 12.0 or any higher version of xTIMEcomposer Tools.

This section provides information on how to program applications using the SDRAM module.

SDRAM Default implementation

For convenience the module_sdram can use a default implementation. When the define SDRAM_DEFAULT_IMPLEMENTATION is set in sdram_conf.h to one of the supported targets then the sdram_server function will act as a call to the specified implementation. The same applies for the sdram_ports structure. The currently supported targets are:
  • PINOUT_V1_IS42S16400F – This corresponds to the ISSI part IS42S16400F in a 20 pin configuration.
  • PINOUT_V1_IS42S16160D – This corresponds to the ISSI part IS42S16160D in a 20 pin configuration.
  • PINOUT_V0 – This is for a legacy 22 pin configuration.

Single SDRAM Support

For a application with a single SDRAM the default implementation should be set. If it is not set then the explicit sdram_server and sdram_ports must be used. The same applied for all the implementation specific defines.

Multiple Homogeneous SDRAM Support

For a application with a single SDRAM the default implementation should be set. For example, to drive two IS42S16400F parts, set the SDRAM_DEFAULT_IMPLEMENTATION to PINOUT_V1_IS42S16400F then the following will create the servers:

chan c,d;
par {
        sdram_server(c, ports_0);
        sdram_server(d, ports_1);
        app_0(c);
        app_1(d);
}

and the ports for the above would have been created by:

struct sdram_ports ports_0 = {
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1G,
        XS1_PORT_1C,
        XS1_PORT_1F,
        XS1_CLKBLK_1
};
struct sdram_ports ports_1 = {
        XS1_PORT_16B,
        XS1_PORT_1J,
        XS1_PORT_1I,
        XS1_PORT_1K,
        XS1_PORT_1L,
        XS1_CLKBLK_1
};

Multiple Heterogeneous SDRAM Support

It is possible for the application to drive multiple heterogeneous SDRAM devices simultaneously. In this case each sdram_server and sdram_ports usage must be explicit to the implementation. For example, to drive an IS42S16400F part and an IS42S16160D part, then the following will create the servers:

chan c,d;
par {
        sdram_server_PINOUT_V1_IS42S16400F(c, ports_0);
        sdram_server_PINOUT_V1_IS42S16160D(d, ports_1);
        app_0(c);
        app_1(d);
}

and the ports for the above would have been created by:

struct sdram_ports_PINOUT_V1_IS42S16400F ports_0 = {
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1G,
        XS1_PORT_1C,
        XS1_PORT_1F,
        XS1_CLKBLK_1
};
struct sdram_ports_PINOUT_V1_IS42S16160D ports_1 = {
        XS1_PORT_16B,
        XS1_PORT_1J,
        XS1_PORT_1I,
        XS1_PORT_1K,
        XS1_PORT_1L,
        XS1_CLKBLK_1
};

Notes

The sdram_server and application must be on the same tile.

Source code structure

Directory Structure

A typical SDRAM application will have at least three top level directories. The application will be contained in a directory starting with app_, the sdram module source is in
the module_sdram directory and the directory module_xcommon contains files required to build the application.

app_[my_app_name]/
module_sdram/
module_xcommon/

Of course the application may use other modules which can also be directories at this level. Which modules are compiled into the application is controlled by the USED_MODULES define in the application Makefile.

Key Files

The following header file contains prototypes of all functions required to use use the SDRAM
module. The API is described in SDRAM API
.

Key Files

File

Description

sdram.h

SDRAM API header file

Module Usage

To use the SDRAM module first set up the directory structure as shown above. Create a file in the app folder called sdram_conf.h and into it insert a define for SDRAM_DEFAULT_IMPLEMENTATION. It should be defined as the implementation you want to use, for example for the Slicekit the following would be correct:

#define SDRAM_DEFAULT_IMPLEMENTATION PINOUT_V1_IS42S16160D

Declare the sdram_ports structure used by the sdram_server. This will look like:

struct sdram_ports sdram_ports = {
        XS1_PORT_16A,
        XS1_PORT_1B,
        XS1_PORT_1G,
        XS1_PORT_1C,
        XS1_PORT_1F,
        XS1_CLKBLK_1
};

Next create a main function with a par of both the sdram_server function and an application function, these will require a channel to connect them. For example:

int main() {
  chan sdram_c;
  par {
    sdram_server(sdram_c, sdram_ports);
    application(sdram_c);
  }
  return 0;
}

Now the application function is able to use the SDRAM server.

The SDRAM memory mapper has a simple interface where to the mm_read_words and mm_write_words a virtual address is passes, this virtual address is mapped to a physical address and the I/O is performed there. The mm_wait_until_idle exists so that the application can run the I/O commands in a non-blocking manner then confirm that the command has when the mm_wait_until_idle returns.

Software Requirements

The component is built on xTIMEcomposer Tools version 12.0.
The component can be used in version 12.0 or any higher version of xTIMEcomposer Tools.

This tutorial describes the demo applications included in the XMOS SDRAM software component.
Recommended Hardware
describes the required hardware setups to run the demos.

app_sdram_demo

This application demonstrates how the module is used to accesses memory on the SDRAM. The purpose of this application is to show how data is written to and read from the SDRAM in a safe manner.

Getting Started

  1. Plug the XA-SK-SDRAM Slice Card into the ‘STAR’ slot of the Slicekit Core Board.
  2. Plug the XA-SK-XTAG2 Card into the Slicekit Core Board.
  3. Ensure the XMOS LINK switch on the XA-SK-XTAG2 is set to “off”.
  4. Open app_sdram_demo.xc and build it.
  5. run the program on the hardware.

The output produced should look like:

0   0
1   1
2   2
3   3
4   4
5   5
SDRAM demo complete.

Notes

  • There are 4 SDRAM I/O commands: sdram_buffer_write, sdram_buffer_read, sdram_full_page_write, sdram_full_page_read. They must all be followed by a sdram_wait_until_idle before another I/O command may be issued. When the sdram_wait_until_idle returns then the data is now at it destination. This functionality allows the application to be getting on with something else whilst the SDRAM server is busy with the I/O.
  • There is no need to explictly refresh the SDRAM as this is managed by the sdram_server.

app_sdram_regress

This application serves as a software regression to aid implementing new SDRAM interfaces and verifying current ones. The demo runs a series of regression tests of increasing difficulty, beginning from using a single core for the sdram_server with one core loaded progressing to all cores being loaded to simulate an XCore under full load.

Getting Started

  1. Plug the XA-SK-SDRAM Slice Card into the ‘STAR’ slot of the Slicekit Core Board.
  2. Plug the XA-SK-XTAG2 Card into the Slicekit Core Board.
  3. Ensure the XMOS LINK switch on the XA-SK-XTAG2 is set to “off”.
  4. Open app_sdram_regress.xc and build it.
  5. run the program on the hardware.

The output produced should look like:

Test suite begin
8 threaded test suite start
Begin sanity_check
...

app_sdram_benchmark

This application benchmarks the performance of the module. It does no correctness testing but instead tests the throughput of the SDRAM server.

Getting Started

  1. Plug the XA-SK-SDRAM Slice Card into the ‘STAR’ slot of the Slicekit Core Board.
  2. Plug the XA-SK-XTAG2 Card into the Slicekit Core Board.
  3. Ensure the XMOS LINK switch on the XA-SK-XTAG2 is set to “off”.
  4. Open app_sdram_benchmark.xc and build it.
  5. run the program on the hardware.

The output produced should look like:

Cores active: 8
Max write: 70.34 MB/s
Max read : 66.82 MB/s
Cores active: 7
Max write: 71.47 MB/s
Max read : 68.08 MB/s
...

XMOS SDRAM Component Read More »

GPIO Com Port Demo Quickstart Guide

sw_gpio_examples COM Port demo : Quick Start Guide

We use the XA-SK-GPIO Slice Card together with the xSOFTip UART to create a UART , and send data to and from a PC COM port.
Also xSOFTip I2C software component to communicate with on board ADC.
This application showcases some of the key software features and serves as an example on how to use APIs of UART and I2C.
This demo features UART data loop back, receives commands from comport, and perform according to the command input.

Install Demonstration Tools on the Host PC

The following tools should be installed on the host system in order to run this application

Hardware Setup

The XP-SKC-L2 Slicekit Core board has four slots with edge conectors: SQUARE, CIRCLE,“TRIANGLE“ and STAR.

To setup up the system refer to the figure and instructions below

  1. Connect XA-SK-GPIO Slice Card to the XP-SKC-L2 Slicekit Core board using the connector marked with the SQUARE.
  2. Connect the XTAG Adapter to Slicekit Core board, and connect XTAG-2 to the adapter.
  3. Connect the XTAG-2 to host PC. Note that a USB cable is not provided with the Slicekit starter kit.
  4. Switch on the power supply to the Slicekit Core board.
  5. Connect a null serial cable to DB-9 connector on XA-SK-GPIO Slice Card. The cable will need a cross over between the UART RX and TX pins at each end.
  6. Connect other end of cable to Host DB-9 connector slot. If the Host does not have an DB-9 Connector slot then use USB-UART cable for the demo. We used the BF-810 USB to Uart adapter (See http://www.bafo.com/products_bf-810_S.asp
    (Part number : BF-810). Any other usb to uart bridge should do just as well.
  7. Identify the serial (COM) port number provided by the Host or the USB to UART adapter and open a suitable terminal software for the selected serial port (refer to the Hercules or SecureCRT documentation above).
  8. Configure the host terminal console program as follows: 115200 baud, 8 bit character length, even parity, 1 stop bit, no hardware flow control. The Transmit End-of-Line character should be set to CR (other options presented will probably be LF and CRLF).
  9. Connect XA-SK-GPIO Slice Card to the XP-SKC-L2 Slicekit Core board.
  10. Connect the XTAG Adapter to Slicekit Core board, XA-SK-XTAG2 connector(xtag slice) and connect XTAG-2 to the adapter.
  11. Connect the XTAG-2 to the computer running xTIMEcomposer.
  12. Switch on the power supply to the Slicekit Core board.
  13. Open the serial device on the host console program
Hardware Setup for GPIO COM Port Demo

/files/images/15822/20/hardware_setup-wide.png

Import and Build the Application

  1. Open xTIMEcomposer, then open the edit perspective (Window->Open Perspective->XMOS Edit).
  2. Locate the 'Slicekit COM Port GPIO Demo' item in the xSOFTip Broswer window and drag it into the Project Explorer window in the xTIMEcomposer. This will also cause the modules on which this application depends (in this case, module_i2c_master, module_uart_rx and module_uart_tx) to be imported as well.
  3. Click on the Slicekit COM Port GPIO Demo item in the Explorer pane then click on the build icon (hammer) in xTIMEcomposer. Check the console window to verify that the application has built successfully.

For help in using xTIMEcomposer, try the xTIMEcomposer tutorials, which you can find by selecting Help->Tutorials from the xTIMEcomposer menu.

Note that the Developer Column in the xTIMEcomposer on the right hand side of your screen provides information on the xSOFTip components you are using. Select the generic UART Receiver component in the xSOFTip Browser, and you will see its description together with links to more documentation for this component. Once you have briefly explored this component, you can return to this quickstart guide by re-selecting 'Slicekit COM Port GPIO Demo' in the xSOFTip Browser and clicking once more on the Quickstart link for the Slicekit Com Port GPIO Demo Quickstart.

Running the Demo

  1. Click on the Run icon (the white arrow in the green circle). A dialog will appear asking which device to cvonnect to. Select XMOS XTAG2.
  2. Look at the configured terminal client application console on the Host.
  3. If the terminal is configured correctly, it should display the following message: WELCOME TO GPIO DEMO (**ECHO DATA MODE ACTIVATED**). In this mode any character typed in from the key board is echoed back. Verify this by typing characters in the terminal console on the host. The typed characters should be echoed back.
  4. When ready, enter command mode by typing >cmd (note, be sure to also type the ‘>’ character). The Console will then show COMMAND MODE ACTIVATED.
  5. Type help in the console window. The help menu will be displayed as sown in the figure below.
Screenshot of Hyperterminal window

/files/images/15822/20/help_menu.png

  1. Type
    setall` in the console to switch ON all the LEDs.
  2. Type clearall to switch OFF all the LEDs.
  3. Type setled N for switching ON a particular LED. ‘N’ ranges from 1 to 4.
  4. Type clearled N for switching OFF a particular LED. ‘N’ ranges from 1 to 4.
  5. Type in chkbuttons to return the status of buttons since last ‘chkbuttons’ command. The console should display COMMAND EXECUTED NO BUTONS ARE PRESSED.
  6. Press a button on the Slice Card. The console should display COMMAND EXECUTED BUTTON 1 PRESSED or COMMAND EXECUTED BUTTON 2 PRESSED
  7. Type in chkbuttons again. The console should display COMMAND EXECUTED BUTTON 1 PRESSED.
  8. Type in readadc for readig ADC value and displaying current temperature. The console should display CURRENT TEMPERATURE VALUE IS : <temperature> C.
  9. Type in exit to leave command mode and go back to ECHO DATA MODE. Verify that once again, typed characters are simply echoed back.

Next Steps

Look at the Code

  1. Examine the application code. In xTIMEcomposer navigate to the src directory under app_sk_gpio_com_demo and double click on the main.xc file within it. The file will open in the central editor window.
  2. This code is quite a bit more complex than the GPIO Simple Demo, since more complex user input must be obtained from the UART and processed.
  3. Find the part of the code which is processing command input from the host console. Check how the Generic UART RX and TX APIs from the General Uart Component library are being applied. As part of this exercise, locate the documentation for these components (Generic UART Receiver and Generic UART Transmitter) in the xSOFTip explorer pane of xTIMEcomposer and review their API documentation.

More complex Serial Bridging Applications

This application uses just one UART which takes up two logical cores. Take a look at the Multi-Uart Component in the xSOFTip Explorer. This fits 8 Uarts into two logical cores. Have a look at the documentation for that component and how its API differs from the stand alone General Uart.

XMOS has also implemented a reference solution for an Ethernet to Serial bridge offering many features including dynamic reconfiguration, an embedded webserver and 8 uarts running up to 115KBaud. To get access to this solution, buy the XA-SK-UART-8 Multi Uart Slice Card from digikey and contact your sales representative to get the reference code.

GPIO Com Port Demo Quickstart Guide Read More »

SliceKit GPIO Example Applications

This document covers example applications that demonstrate various features of the XA-SK-GPIO Slice Card including the ADC, LEDs, UART connector and buttons, the I2C master xSOFTip component, as well as various basic features of the xCORE processor.

Low level details of how GPIO example application is implemented are covered here, with information about how to modify and experiment with them.

For getting started instructions for these applications, please refer to their respective Quick Start guides.

This application may be evaluated using the Slicekit Modular Development Platform, available from digikey. Required board SKUs are:

  • XP-SKC-L2 (Slicekit L2 Core Board) plus XA-SK-GPIO plus XA-SK-XTAG2 (Slicekit XTAG adaptor) plus XTAG2 (debug adaptor)

Example Applications

app_slicekit_simple_demo

This application has the following features:

  • module_i2c_master from the xSOFt ip library is used to access the external ADC, which is equipped with an external linearised thermistor circuit for temperature sensing.
  • simple code to print the recorded temperature to the XDE debug console on the press of one of the Slice Card buttons
  • simple code to cycle through the 4 LEDs each time the other button is pressed.
  • demonstrates use of XC select statements for handling multiple concurrent inputs
  • demonstrates basic usage of XCore ports

app_slicekit_com_demo

This application extends the simple demo to provide the following functionality (all options are dynamically reconfigurable via the APIs for app_slicekit_com_demo application):

  • Uart RX and TX Using the generic Uart RX and TX xSOFTip components
    • Baud Rate: 150 to 115200 bps
    • Parity: None, Mark, Space, Odd, Even
    • Stop Bits: 1,2
    • Data Length: 1 to 30 bits (Max 30 bits assumes 1 stop bit and no parity)
  • Cycles Through LEDs on button Press
  • Displays temperature value and button press events on the terminal console of a host PC via the UART

app_sk_gpio_eth_combo_demo

  • XA-SK-E100 Ethernet Slice Card is additionally required for this demo

This application extends the GPIO com port demo to utilize Ethernet and XTCP components in order to host a web page to

  • Turn GPIO Slice Card LEDs on and off
  • Display GPIO Slice Card button press status
  • Read the room temperature via the onboard ADC and display on the web page

app_sk_gpio_wifi_tiwisl_combo_demo

  • XA-SK-WIFI Slice Card is additionally required for this demo

This application extends the GPIO com port demo to utilize Wi-Fi component in order to host a web page to

  • Turn GPIO Slice Card LEDs on and off
  • Display GPIO Slice Card button press status
  • Read the room temperature via the on-board ADC and display on the web page

Simple Demo

Structure

All of the files required for operation are located in the app_sk_gpio_simple_demo/src directory. The files that are need to be included for use of this component in an application are:

File common.h

Description Header file for API interfaces and Look up tables for thermistor.

main.xc

Main file which implements the demo functionality

API

  • void app_manager(chanend c_uartTX, chanend c_chanRX, chanend c_process, chanend c_end)

    Polling uart RX and push button switches and send received commands to process_data thread.

    Parameters

    • c_uartTX

      Channel to Uart TX Thread

    • c_chanRX

      Channel to Uart RX Thread

    • c_process

      Channel to process data Thread

    • c_end

      Channel to read data from process thread

  • int linear_interpolation(int adc_value)

    Calculates temperatue based on linear interpolation.

    Parameters

    • adc_value

      int value read from ADC

    Returns

    Returns linear interpolated Temperature value

  • int read_adc_value()

    Read ADC value using I2C.

    Returns

    Returns ADC value

Usage and Implementation

The port declaration for the LEDs, Buttons and I2C are declared as below. LEDs and Buttons use 4 bit ports and I2C uses 1 bit port for SCL(I2c Clock) and SDA (I2C data).

on stdcore[CORE_NUM]: out port p_led=XS1_PORT_4A;
on stdcore[CORE_NUM]: port p_PORT_BUT_1=XS1_PORT_4C;
on stdcore[CORE_NUM]: struct r_i2c i2cOne = {
		XS1_PORT_1F,
		XS1_PORT_1B,
		1000
 };

The app_manager API writes the configuration settings information to the ADC as shows below.

	i2c_master_write_reg(0x28, 0x00, data, 1, i2cOne); //Write configuration information to ADC

The select statement in the app_manager API selects one of the two cases in it, checks if there is IO event or timer event. This statement monitors both the events and executes which ever event is occurred first.
The select statement in the application is listed below. The statement checks if there is button press or not. If there is button press then it looks if the button state is same even after 20msec. If the buton state is same then it recognises as an valid push.

		select
		{
			case button => p_PORT_BUT_1 when pinsneq(button_press_1):> button_press_1: //checks if any button is pressed
				button=0;
				t:>time;
				break;

			case !button => t when timerafter(time+debounce_time):>void: //waits for 20ms and checks if the same button is pressed or not
				p_PORT_BUT_1:> button_press_2;
				if(button_press_1==button_press_2)
				if(button_press_1 == BUTTON_PRESS_VALUE) //Button 1 is pressed
				{
					printstrln("Button 1 Pressed");
					p_led<:(led_value);
					led_value=led_value<<1;
					led_value|=0x01;
					led_value=led_value & 0x0F;
					if(led_value == 15)
					{
						led_value=0x0E;
					}
				}
				if(button_press_1 == BUTTON_PRESS_VALUE-1) //Button 2 is pressed
				{
					data1[0]=0;data1[1]=0;
					i2c_master_rx(0x28, data1, 2, i2cOne); //Read ADC value using I2C read 
					printstrln("Reading Temperature value....");
					data1[0]=data1[0]&0x0F;
					adc_value=(data1[0]<<6)|(data1[1]>>2);
					printstr("Temperature is :");
					printintln(linear_interpolation(adc_value));
				}

				button=1;
				break;
		}

After recognising the valid push then it checks if Button 1 is pressed or Button 2 is pressed. IF Button 1 is pressed then, the application reads the status of LEDs and shift the position of the LEDs to left by 1.
If Button 2 is pressed, then the applciation reads the contents of ADC register using I2C read instruction and input the ADC value to linear interpolation function as shown below.

int linear_interpolation(int adc_value)
{
	int i=0,x1,y1,x2,y2,temper;
	while(adc_value<TEMPERATURE_LUT[i][1])
	{
		i++;
	}
//::Formula start
	//Calculating Linear interpolation using the formula y=y1+(x-x1)*(y2-y1)/(x2-x1)
//::Formula
	x1=TEMPERATURE_LUT[i-1][1];
	y1=TEMPERATURE_LUT[i-1][0];
	x2=TEMPERATURE_LUT[i][1];
	y2=TEMPERATURE_LUT[i][0];
	temper=y1+(((adc_value-x1)*(y2-y1))/(x2-x1));
	return temper;//Return Temperature value
}

The linear intepolation function calculates the linear interpolation value using the following formula and returns the temperature value from temperature look up table.

	//Calculating Linear interpolation using the formula y=y1+(x-x1)*(y2-y1)/(x2-x1)

int TEMPERATURE_LUT[][2]= //Temperature Look up table
{
		{-10,850},{-5,800},{0,750},{5,700},{10,650},{15,600},{20,550},{25,500},{30,450},{35,400},
		{40,350},{45,300},{50,250},{55,230},{60,210}
};

COM Port Demo

Structure

All of the files required for operation are located in the app_slicekit_simple_demo/src directory. The files that are need to be included for use of this component in an application are:

File common.h

Description Header file for API interfaces and Look up tables for thermistor. FIXME – what about the uart

main.xc

Main file which implements the demo functionality

API

  • void app_manager(chanend c_uartTX, chanend c_chanRX, chanend c_process, chanend c_end)

    Polling uart RX and push button switches and send received commands to process_data thread.

    Parameters

    • c_uartTX

      Channel to Uart TX Thread

    • c_chanRX

      Channel to Uart RX Thread

    • c_process

      Channel to process data Thread

    • c_end

      Channel to read data from process thread

  • void process_data(chanend c_process, chanend c_end)

    process received data to see if received data is valid command or not Polling switches to see for button press

    Parameters

    • c_process

      Channel to receive data from app manager Thread

    • c_end

      Channel to communicate to app manager thread

  • void uart_tx_string(chanend c_uartTX, unsigned char message[100])

    Transmits byte by byte to the UART TX thread for an input string.

    Parameters

    • c_uartTX

      Channel to receive data from app Uart TX Thread

    • message

      Buffer to store array of characters

  • int linear_interpolation(int adc_value)

    Calculates temperatue based on linear interpolation.

    Parameters

    • adc_value

      int value read from ADC

    Returns

    Returns linear interpolated Temperature value

  • int read_adc_value()

    Read ADC value using I2C.

    Returns

    Returns ADC value

Usage and Implementation

The port declaration for the LEDs, Buttons, I2C and UART are declared as below. LEDs and Buttons uses 4 bit ports, UART uses 1 bit ports both for Transmit and Receive and I2C uses 1 bit port for SCL(I2c Clock) and SDA (I2C data).

#define CORE_NUM 1
#define BUTTON_PRESS_VALUE 2
on stdcore[CORE_NUM] : buffered in port:1 p_rx =  XS1_PORT_1G;
on stdcore[CORE_NUM] : out port p_tx = XS1_PORT_1C;
on stdcore[CORE_NUM]: port p_led=XS1_PORT_4A;
on stdcore[CORE_NUM]: port p_button1=XS1_PORT_4C;
on stdcore[CORE_NUM]: struct r_i2c i2cOne = {
		XS1_PORT_1F,
		XS1_PORT_1B,
		1000
 };

The app_manager API writes the configuration settings information to the ADC as shows below.

	i2c_master_write_reg(0x28, 0x00, i2c_register, 1, i2cOne); //Configure ADC by writing the settings to register

The select statement in the app_manager API selects one of the three cases in it, checks if there is IO event or timer event or any event on the Uart Receive pin. This statement monitors all the events and executes which ever event is occurred first.
The select statement in the applciation is listed below. The statement checks if there is button press or availability of data on the Uart Receive pin. If there is button press then it looks if the button state is same as even after 200msec. If the buton state is same then it recognises as a valid push.
If there is data on the Uart Receive pin the it echoes the data back to the uart Transmit pin until > character is received in the input data.

		select
		{
			case c_end:>data:
				c_end:>data;
				if(data == BUTTON_1) //Cycle LEDs on button 1 press
				{
					printstrln("Button 1 Pressed");
					p_led<:(led_value);
					led_value=led_value<<1;
					if(led_value == 16) //If LED value is 16 then assigns LED value to 1 which cycles LEDs by button press
					{
						led_value=0x01;
					}
				}
				if(data == BUTTON_2) //Displays Temperature on console if Button 2 is pressed
				{
					adc_value=read_adc_value();
					data_arr[0]=(linear_interpolation(adc_value));
					printstr("Temperature is :");
					printint(linear_interpolation(adc_value));
					printstrln(" C");
				}
				break;
			case uart_rx_get_byte_byref(c_uartRX, rxState, buffer):
//::Command start
				if(buffer == '>') //IUF received data is '>' character then expects cmd to endter into command mode
				{
					j=0;
					uart_rx_get_byte_byref(c_uartRX, rxState, buffer);
					cmd_rcvbuffer[j]=buffer;
					if((cmd_rcvbuffer[j] == 'C' )|| (cmd_rcvbuffer[j] =='c')) //Checks if received data is 'C' or 'c'
					{
						j++;
						uart_rx_get_byte_byref(c_uartRX, rxState, buffer);
						cmd_rcvbuffer[j]=buffer;

						if((cmd_rcvbuffer[j] == 'm' )|| (cmd_rcvbuffer[j] =='M')) //Checks if received data is 'M' or 'm'
						{
							j++;
							uart_rx_get_byte_byref(c_uartRX, rxState, buffer);
							cmd_rcvbuffer[j]=buffer;
							if((cmd_rcvbuffer[j] == 'D' )|| (cmd_rcvbuffer[j] =='d'))//Checks if received data is 'D' or 'd'
							{
								uart_tx_send_byte(c_uartTX, '\r');
								uart_tx_send_byte(c_uartTX, '\n');
								uart_tx_string(c_uartTX,CONSOLE_MESSAGES[0]);
								COMMAND_MODE=1; //activates command mode as received data is '>cmd'
								uart_tx_send_byte(c_uartTX, '\r');
								uart_tx_send_byte(c_uartTX, '\n');
								uart_tx_send_byte(c_uartTX, '>'); //displays '>' if command mode is activated
							}
							else
							{
								uart_tx_send_byte(c_uartTX, '>');
								for(int i=0;i<3;i++)
									uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[i]); // if received dta is not 'c' displays back the received data
							}
						}
						else
						{
							uart_tx_send_byte(c_uartTX, '>'); //if received data is not 'm' displays the received data
							for(int i=0;i<2;i++)
								uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[i]);
						}
					}
					else
					{
						uart_tx_send_byte(c_uartTX, '>');
						uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[j]);
						j=0;
					}
				}
				else
				{
					uart_tx_send_byte(c_uartTX,buffer); //Echoes back the input characters if not in command mode
				}
//::Command
				while(COMMAND_MODE) //Command mode activated
				{
					j=0;
					skip=1;
					while(skip == 1)
					{
//::Send to process start					
						select
						{
							case uart_rx_get_byte_byref(c_uartRX, rxState, buffer):
								cmd_rcvbuffer[j]=buffer;
								if(cmd_rcvbuffer[j++] == '\r')
								{
									skip=0;
									j=0;
									while(cmd_rcvbuffer[j] != '\r')
									{
										c_process<:cmd_rcvbuffer[j]; //received valid command and send the command to the process_data theread
										uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[j]);
										j++;
									}
									cmd_rcvbuffer[j]='\0';
									c_process<:cmd_rcvbuffer[j];
									for(int inc=0;inc<20;inc++) //Clears the command buffer
										cmd_rcvbuffer[inc]='0';
									j=0;
								}
								break;
//::Send
							case c_end:>data:
								if(data!=EXIT && data!=INVALID )
								{
									uart_tx_string(c_uartTX,CONSOLE_MESSAGES[3]); //Displays COmmand Executed Message on Uart
								}
//::State machine
								switch(data)
								{
									case EXIT: //Exit from command mode
										COMMAND_MODE=0;
										skip=0;
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[1]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[13]);
										break;

									case SET_LED_1: //Read port Value and Set LED 1 ON
										p_led:>data;
										data=data | 0xE;
										p_led<:data;
										break;

									case CLEAR_LED_1://Read port Value and Set LED 1 OFF
										p_led:>data;
										p_led<:data&0x1;
										break;

									case SET_LED_2: //Read port Value and Set LED 2 ON
										p_led:>data;
										p_led<:data | 0xD;
										break;

									case CLEAR_LED_2: //Read port Value and Set LED 2 OFF
										p_led:>data;
										p_led<:data&0x2;

										break;

									case SET_LED_3: //Read port Value and Set LED 3 ON
										p_led:>data;
										p_led<:data | 0xB;
										break;

									case CLEAR_LED_3: //Read port Value and Set LED 3 OFF
										p_led:>data;
										p_led<:data&0x4;
										break;

									case SET_LED_4: //Read port Value and Set LED 4 ON
										p_led:>data;
										p_led<:data | 0x7;
										break;

									case CLEAR_LED_4: //Read port Value and Set LED 4 OFF
										p_led:>data;
										p_led<:data&0x8;

										break;

									case CLEAR_ALL: //sets all four LEDs OFF
										p_led<:0xF;
										break;

									case SET_ALL: //sets all four LEDs ON
										p_led<:0x0;
										break;

									case BUTTON_PRESSED: //Checks if button is pressed
										c_end:>button;
										if(button == BUTTON_1) //Prints Button 1 is pressed on the Uart
										{
											CONSOLE_MESSAGES[4][9]='1';
											uart_tx_string(c_uartTX,CONSOLE_MESSAGES[4]);
											button1_press=1;
										}
										if(button == BUTTON_2) //Prints Button 2 is pressed on Uart
										{
											CONSOLE_MESSAGES[4][9]='2';
											uart_tx_string(c_uartTX,CONSOLE_MESSAGES[4]);
											button2_press=1;
										}
										break;
									case HELP: //Displays help messages on Uart
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[14]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[7]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[8]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[9]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[10]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[15]);
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[11]);
										uart_tx_send_byte(c_uartTX, '\r');
										uart_tx_send_byte(c_uartTX, '\n');
										break;
									case READ_ADC: //Displays temperature value on the Uart
										adc_value=read_adc_value();
										data_arr[0]=(linear_interpolation(adc_value));
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[12]);
										uart_tx_send_byte(c_uartTX, (data_arr[0]/10)+'0');
										uart_tx_send_byte(c_uartTX, (data_arr[0]%10)+'0');
										uart_tx_send_byte(c_uartTX, 32);
										uart_tx_send_byte(c_uartTX, 'C');
										break;
									case INVALID: //Displays command input is invalid command on the Uart
										uart_tx_string(c_uartTX,CONSOLE_MESSAGES[2]);
										break;
									case CHK_BUTTONS: //Checks if button are pressed and displays on the Uart
										if(button1_press)
										{
											CONSOLE_MESSAGES[4][9]='1';
											uart_tx_string(c_uartTX,CONSOLE_MESSAGES[4]); //Displays Button 1 is pressed
										}
										if(button2_press)
										{
											CONSOLE_MESSAGES[4][9]='2';
											uart_tx_string(c_uartTX,CONSOLE_MESSAGES[4]); //Dipslays Button 2 is pressed
										}
										if( !button1_press && !button2_press)
										{
											uart_tx_string(c_uartTX,CONSOLE_MESSAGES[5]); //Displays No Buttons are pressed
										}
										button1_press=0;
										button2_press=0;
                                                                                break;
								}
								if(data != EXIT) //Exits from command mode
								{
									uart_tx_send_byte(c_uartTX, '\r');
									uart_tx_send_byte(c_uartTX, '\n');
									uart_tx_send_byte(c_uartTX, '>');
								}
								break;
						}//select
//::State
					}//skip
					j=0;
				}//command mode
				break;
		}//main select

If the received data is > character the it waits to see if the next received successive bytes are c, m and d. If the successive received data is >cmd then the application activates comman mode otherwise the data is echoed back to the Uart Transmit pin. The part of code which explains about the command mode is as blow.

				if(buffer == '>') //IUF received data is '>' character then expects cmd to endter into command mode
				{
					j=0;
					uart_rx_get_byte_byref(c_uartRX, rxState, buffer);
					cmd_rcvbuffer[j]=buffer;
					if((cmd_rcvbuffer[j] == 'C' )|| (cmd_rcvbuffer[j] =='c')) //Checks if received data is 'C' or 'c'
					{
						j++;
						uart_rx_get_byte_byref(c_uartRX, rxState, buffer);
						cmd_rcvbuffer[j]=buffer;

						if((cmd_rcvbuffer[j] == 'm' )|| (cmd_rcvbuffer[j] =='M')) //Checks if received data is 'M' or 'm'
						{
							j++;
							uart_rx_get_byte_byref(c_uartRX, rxState, buffer);
							cmd_rcvbuffer[j]=buffer;
							if((cmd_rcvbuffer[j] == 'D' )|| (cmd_rcvbuffer[j] =='d'))//Checks if received data is 'D' or 'd'
							{
								uart_tx_send_byte(c_uartTX, '\r');
								uart_tx_send_byte(c_uartTX, '\n');
								uart_tx_string(c_uartTX,CONSOLE_MESSAGES[0]);
								COMMAND_MODE=1; //activates command mode as received data is '>cmd'
								uart_tx_send_byte(c_uartTX, '\r');
								uart_tx_send_byte(c_uartTX, '\n');
								uart_tx_send_byte(c_uartTX, '>'); //displays '>' if command mode is activated
							}
							else
							{
								uart_tx_send_byte(c_uartTX, '>');
								for(int i=0;i<3;i++)
									uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[i]); // if received dta is not 'c' displays back the received data
							}
						}
						else
						{
							uart_tx_send_byte(c_uartTX, '>'); //if received data is not 'm' displays the received data
							for(int i=0;i<2;i++)
								uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[i]);
						}
					}
					else
					{
						uart_tx_send_byte(c_uartTX, '>');
						uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[j]);
						j=0;
					}
				}
				else
				{
					uart_tx_send_byte(c_uartTX,buffer); //Echoes back the input characters if not in command mode
				}

After the command mode is active the applicaion receives all the input commands and send to the process_data API using a channel.The part of the code is shown below.

						select
						{
							case uart_rx_get_byte_byref(c_uartRX, rxState, buffer):
								cmd_rcvbuffer[j]=buffer;
								if(cmd_rcvbuffer[j++] == '\r')
								{
									skip=0;
									j=0;
									while(cmd_rcvbuffer[j] != '\r')
									{
										c_process<:cmd_rcvbuffer[j]; //received valid command and send the command to the process_data theread
										uart_tx_send_byte(c_uartTX, cmd_rcvbuffer[j]);
										j++;
									}
									cmd_rcvbuffer[j]='\0';
									c_process<:cmd_rcvbuffer[j];
									for(int inc=0;inc<20;inc++) //Clears the command buffer
										cmd_rcvbuffer[inc]='0';
									j=0;
								}
								break;

The process_data thread checks if any button is pressed or checks if there is any command from app_manager thread. If there is button press then the thread sends instructions to the app_manager thread about the button or if command is received, then it send instructions about teh command received.
The details in the process_data thread is as shown below.


Process_data thread send instructions to the app_manager thread about the command received. The app_manager thread then implementys the state machine according to the instructions received from the process_data thread. The state machine of app_manager thread is as below.

GPIO Ethernet Combo Demo

Structure

All the files required for operation are located in the app_sk_gpio_eth_combo_demo/src directory. The files to be included for use of the dependent components are:

File

Description

ethernet_board_support.h

Defines OTP and ethernet pins required for Ethernet component

xtcp.h

Header file for xtcp API interface

web_server.h

Header file for web server API interface in order to use web pages

i2c.h

Defines i2c pins and API interface to use i2c master component for GPIO adc interfacing

app_handler.h

Application specific defines and API interface to implement demo functionality

API

doxygenfunction: Cannot find function “app_handler” in doxygen xml output

doxygenfunction: Cannot find function “process_web_page_data” in doxygen xml output

doxygenfunction: Cannot find function “get_web_user_selection” in doxygen xml output

Usage and Implementation

The port declaration for Ethernet, LEDs, Buttons and I2C are declared as below:
  • Ethernet uses ethernet_board_support.h configuration
  • I2C uses 1 bit port for SCL(I2C Clock) and SDA (I2C data)
  • LEDs and Buttons uses 4 bit ports

The app_manager API writes the configuration settings to the ADC as shows below

The select statement in the app_handler API selects either I/O events to check for any valid button presses or uses channel events to detect any commands from web page requests. Valid web page commands are either to set or reset LEDs and check button press state since last check request.

Whenever there is a change in values of the button ports, a flag is used to kick start a timer for debounce interval, and port value is sampled to identify which button is pressed. The code is as shown below

Every time a web page request is received, app_handler records current ADC value and button press status and sends it to web page.
Button check statuses are reset immediately after the web page request.

Using sc_website to build web page for this demo application

Makefile in app_sk_gpio_eth_combo_demo folder should include the following line:

WEBFS_TYPE = internal

This value indicates sc_website component to use program memory instead of FLASH memory to store the web pages.

As a next step, create web folder in app_sk_gpio_eth_combo_demo

In order to include any images to be displayed on the web page, create images folder as follows
app_sk_gpio_eth_combo_demo/web/images

For this application, we have created index.html web page using html script. This page uses XMOS logo from images folder. We have defined desired GPIO controls for LEDs in this web page.

APIs that are required to be executed by the demo application should be enclosed between the tags {% and %}. These are to be defined in web_page_functions.c file.
For example, index.html contains
<p>{% read_temperature(buf, app_state, connection_state) %}</p>

This indicates read_temperature is a function executed by the program and result is returned to the web page. After execution, sc_website component replaces this function as
<p>”Temperature recorded from onboard ADC: <b>NA </b><sup>o</sup>C”</p>

GPIO Wi-Fi Combo Demo

Structure

All the files required for operation are located in the app_sk_gpio_wifi_tiwisl_combo_demo/src directory. The files to be included for use of the dependent components are:

File

Description

wifi_tiwisl_server.h

Header file for Wi-Fi API interface

web_server.h

Header file for web server API interface in order to use web pages

i2c.h

Defines i2c pins and API interface to use i2c master component for GPIO adc interfacing

app_handler.h

Application specific defines and API interface to implement demo functionality

API

doxygenfunction: Cannot find function “app_handler” in doxygen xml output

doxygenfunction: Cannot find function “process_web_page_data” in doxygen xml output

doxygenfunction: Cannot find function “get_web_user_selection” in doxygen xml output

Usage and Implementation

The port declaration for Wi-Fi (SPI), LEDs, Buttons and I2C are declared as below:
  • Wi-Fi control uses
    • 1 four-bit port for nCS(Chip Select) and Power enable
    • 1 one-bit port for nIRQ(interrupt)
  • SPI uses 3 one-bit ports for MOSI, CLK and MISO
  • I2C uses 1 bit port for SCL(I2C Clock) and SDA (I2C data)
  • LEDs and Buttons use 4 bit ports

The app_manager API writes the configuration settings to the ADC as shows below

The select statement in the app_handler API selects either I/O events to check for any valid button presses or uses channel events to detect any commands from web page requests. Valid web page commands are either to set or reset LEDs and check button press state since last check request.

Whenever there is a change in values of the button ports, a flag is used to kick start a timer for debounce interval, and port value is sampled to identify which button is pressed. The code is as shown below

Every time a web page request is received, app_handler records current ADC value and button press status and sends it to web page.
Button check statuses are reset immediately after the web page request.

Using sc_website to build web page for this demo application

Makefile in app_sk_gpio_wifi_tiwisl_combo_demo folder should include the following line:

WEBFS_TYPE = internal

This value indicates sc_website component to use program memory instead of FLASH memory to store the web pages.

As a next step, create web folder in app_sk_gpio_wifi_tiwisl_combo_demo

In order to include any images to be displayed on the web page, create images folder as follows
app_sk_gpio_wifi_tiwisl_combo_demo/web/images

For this application, we have created index.html web page using html script. We have defined desired GPIO controls for LEDs in this web page.

APIs that are required to be executed by the demo application should be enclosed between the tags {% and %}. These are to be defined in web_page_functions.c file.
For example, index.html contains
<p>{% read_temperature(buf, app_state, connection_state) %}</p>

This indicates read_temperature is a function executed by the program and result is returned to the web page. After execution, sc_website component replaces this function as
<p>”Temperature recorded from on-board ADC: <b>NA </b><sup>o</sup>C”</p>

SliceKit GPIO Example Applications Read More »

Scroll to Top