Open Game Station

A modular, open hardware gaming platform for classic 8-bit games

Sep 18, 2020

Project update 6 of 8

How to Create or Modify Module Firmware

by Longan Lab

We currently offer a number of card modules that you can use with Open Game Station, and there will be more in the future. And the open source community has provided many ready-made and interesting games that you can play. But those of you who get to know our hardware and our firmware will be in a position to develop games that are even more fun to play. And you can implement those games—or the hardware functionality upon which they depend—as card modules.

Creating a card module is not very difficult. This update describes the process by which you can write or modify the firmware of a card. In our next update, we will talk about the hardware aspects of these expansion modules.

The Skills You Need

If you want to write or modify the firmware of a Card, you will need:

Writing Firmware

Writing or modifying card module firmware involves a few different steps. Let’s take a look at the firmware for the BME280 Card. If you open the file linked above, you will see that it includes six sections.

Section 1 - Header Files & Class Definitions

    /*---1-START----------------------------------------------------------
     -
     - Add the library to read the sensor here
     - Add the class object here if need
     -
     --------------------------------------------------------------------*/
    #include 
       "Seeed_BME280.h"                                                                                
    BME280 bme280;                                                      
    /*---1-END-----------------------------------------------------------*/

Here we add the header files that need to be called and the object that defines the sensor. This part of the content is only needed for those sensors with a driver library. For a simple sensor, such as a button that just needs to read an IO or analog value, we don’t need a driver.

Section 2 - Setting the Sensor-Refresh Time

    /*---2-START----------------------------------------------------------
     -
     - SENSOR UPDATE TIME, DEFAULT TO 10ms
     -
     --------------------------------------------------------------------*/
    #define SENSOR_UPDATE_TIME  10      // ms
    /*---2-END-----------------------------------------------------------*/

The unit is milliseconds, and the default is 10 milliseconds. If the update time of some sensors is slow, you can change this time to a more reasonable value.

Section 3 - Setting Other Sensor Information

    /*---3-START----------------------------------------------------------
     -
     - SET THE SENSOR INFOS
     -
     --------------------------------------------------------------------*/
    void valueInfoSet()
    {
        dtaCnt = 4;                
        dtaType[0] = DTA_TYPE_FLOAT;                // temp
        dtaUnit[0] = UNIT_TEMPERATURE;
        nFloat[0]  = 0;
        dtaType[1] = DTA_TYPE_INT;                  // humidity
        dtaUnit[1] = UNIT_HUMIDITY;
        nFloat[1]  = 0;
        dtaType[2] = DTA_TYPE_FLOAT;                // press, kpa
        dtaUnit[2] = UNIT_PRESS;
        nFloat[2]  = 2;
        dtaType[3] = DTA_TYPE_FLOAT;                // attidude, meter
        dtaUnit[3] = UNIT_ALTITUDE;
        nFloat[3]  = 2;
    }
    /*---3-END-----------------------------------------------------------*/

dtaCnt identifies the number of sensors. The BME280 card, for example, contains four sensors—temperature, humidity, air pressure, and altitude—so dtaCnt is 4. For the three-axis acceleration sensor, on the other hand, dtaCnt is 3. Many sensors, including temperature and photosensitive sensors, will have dtaCnt set to 1. In that case, you can delete the dtaType[1], dtaUnit[1], dtaUnit[2], etc.

dtaType[n] specifies the type of the sensor value:

dtaUnit[n] specifies the unit type:

This list is defined in CardsDfs.h. If you add a sensor, you will need to expand this definition. (Or you can contact us, and we’ll add it upstream.)

nFloat[n] is the number of digits after the decimal point. It is irrelevant for non-float values and, if the value type of a sensor is flexible, it should be set it to 0. For a float, it will depend on the situation, but 2 is a good default. For highly precise sensors, you can use a larger number.

Section 4 - Initialization

    /*---4-START----------------------------------------------------------
     -
     - INITIALIZE THE SENSOR
     -
     --------------------------------------------------------------------*/
    void sensorInit()
    {
        if(!bme280.init()){
            Serial.println("Device error!");
        }
    }
    /*---4-END-----------------------------------------------------------*/

This section allows you to initialize the sensor. If you have nothing to initialized, you can just delete the code in the sensorInit() function, but make sure to retain the sensorInit() function.

Section 5 - Set Card Information

    /*---5-START----------------------------------------------------------
     -
     - SET CARD INFOS
     -
     --------------------------------------------------------------------*/
    void cardInfoInit()
    {
        cardInfo.setInfo(0x08,                  // I2C ADDR
                         0x05,                  // NO. of Card system
                         dtaCnt,                // Quantity of Sensors
                         6,                     // LENGTH OF NAME
                         "BME280",              // NAME OF SENSOR, max 20 char
                         1011008,               // SKU
                         1.0);                  // VERSION
    }
    /*---5-END-----------------------------------------------------------*/

This section defines other information about the card. It includes seven values:

Section 6 - Get sensor values

    /*---6-START----------------------------------------------------------
     -
     - UPDATE SENSOR VALUE
     -
     --------------------------------------------------------------------*/
    void sensorUpdate()
    {
        static unsigned long timer_s = 0;
        if(millis()-timer_s < SENSOR_UPDATE_TIME)return;
        timer_s = millis();
        valueSensor[0] = bme280.getTemperature();
        valueSensor[1] = bme280.getHumidity();
        valueSensor[2] = bme280.getPressure()/1000.0;
        valueSensor[3] = bme280.calcAltitude(valueSensor[2]*1000.0);
    }
    /*---6-END-----------------------------------------------------------*/

To read the sensor value, just assign valueSensor[n]. (If there is only one sensor, you can delete valueSensor[1], valueSensor[2], etc.) If necessary, you can add other functions above void sensorUpdate() to read sensor values for use in the sensorUpdate function.

Next week, we will cover the art and science of manufacturing a physical card module for Open Game Station! module!


Sign up to receive future updates for Open Game Station.

Subscribe to the Crowd Supply newsletter, highlighting the latest creators and projects