This is the multi-page printable view of this section. Click here to print...

Return to the regular view of this page

As of 2025-09-10

TWENET reference

Core libraries behind MWX and TWELITE Apps
Information on the TWENET library. Contains material for internal development.

List of Reference Information for General Development

Below is a list of materials that may be referenced for general development purposes.

Development using Act (MWX C++ Library)

For development using Act (MWX library), please refer to:

Development using TWENET C (C language)

Development using TWENET C (C language), with APIs provided by semiconductor manufacturers and the TWENET library. Many TWELITE Apps are written in TWENET C.

  • TWENTEcmpt Library — A compatibility library for AHI functions (APIs provided by semiconductor manufacturers for BLUE/RED) implemented for TWELITE GOLD.

  • TWENETutils Library — Macros and library functions mainly used in TWENET C.

Other Libraries

1 - TWENETmcu - Microcontroller Library

Library supporting the basic operation of the microcontroller
Contains source code for basic microcontroller operations.

TWENETmcu - Microcontroller Library

Contains source code for basic microcontroller operations. Much of the code is copied from the JN5189 SDK and partially adapted for TWENET. It also includes the startup functions main() and WarmMain() that run TWENET.

  • board - Hardware initialization (clock, GPIO pins, etc.)
  • component - Libraries providing higher-level functionality (from SDK_X.Y.Z/components, middleware, etc.)
  • framework - Higher-level libraries (from SDK_X.Y.Z/middleware/wireless/framework)
  • device, startup - HAL layer for JN5189
  • drivers - FSL libraries and others for peripheral operations
  • libs - Library files (libXXX.a)
  • main - main() and debug output functions like _putchar()
  • printf - printf() library (does not use NewLib)
  • uMac - Contains MMAC.h
  • utilities - assert() and debug functions like PRINTF()

Technical Documentation

This section describes implementation details of TWENET and considerations for developing application programs.

1.1 - About Microcontrollers

About microcontrollers
Notes on the microcontroller of TWELITE GOLD.

About Microcontrollers

The microcontroller used in TWELITE GOLD is an ARM CortexM4 core with IEEE802.15.4. TWELITE BLUE/RED use an OpenRISC core, which is a completely different microcontroller, and there are several points to note.

  • While we have described content that requires special attention in terms of specifications, deeper information may be needed depending on the system and hardware requirements you are creating. For more details, please refer to the NXP JN5189 datasheet.

About the descriptions in this document

  • This document mainly describes the differences from the usage with TWELITE BLUE/RED, but please refer to the JN5189 datasheet as the primary source.
  • When expressing pin numbers, PIO indicates the original number of the microcontroller, while DIO/DO indicates the pin names used in TWELITE BLUE/RED. ADC1 and ADC2 are used in the same way depending on the context.
  • To facilitate the porting of applications, we provide the “AHI subset” library. This library is intended for porting some of the applications we have implemented. Therefore, the behavior may differ from the API on TWELITE BLUE/RED.

Microcontroller Differences

  • TWELITE BLUE/RED are big-endian, but TWELITE GOLD is little-endian.
  • The ARM CortexM4 is an architecture with flexible clock configuration. As a general rule, the microcontroller’s operating clocks are 12MHz/32MHz/48MHz, and IO (such as PWM) operates at 32MHz. The main clocks for TWELITE BLUE/RED are 16MHz/32MHz, and the IO is 16MHz.
  • There are restrictions on using GPIO interrupts per pin. You can use GINT (Group Interrupts) to generate an interrupt when each pin changes.
    • This is implemented in the AHI subset. Since it is intended for porting our application code, it is not a comprehensive implementation, and some specifications and behaviors may differ.
    • In the GINT implementation, interrupts are always generated on both edges.
      • For example, if you have a pin that you want to set to a falling edge and its initial state is LOW. If the pin state transitions from LOW -> HIGH -> LOW, an interrupt will be generated for both LOW -> HIGH and HIGH -> LOW.
      • While the microcontroller is running, the AHI subset suppresses the former, but when used for waking from sleep, software cannot suppress it, and it will wake up at the timing of the LOW -> HIGH transition.
      • Conversely, both edges can be detected, which was not possible with TWELITE BLUE/RED, and this is also reflected in the AHI subset (vAHI_DioInterruptEdge(), vAHI_DioWakeEdge()).
    • There is a PINT function as an interrupt function for each pin. The maximum number of pins that can be used with PINT is fixed.
      • This function is not used in the AHI subset and there are no special procedures for its combined use.

Microcontroller Functions

  • It has a built-in RTC. While TWELITE BLUE/RED could improve timer accuracy by connecting an external oscillator, TWELITE GOLD has a built-in 32kHz oscillator and an RTC function.
  • A circuit for floating-point arithmetic is not included. Calculations are performed by a software library, as before. However, the Cortex-M4 has a DSP function that uses fixed-point arithmetic, so using this is also an option.

Module Differences

  • TWELITE RED/BLUE had a total of 24 pins, including 20 DIO pins, 2 dedicated SPI pins, and 2 dedicated analog pins. In contrast, TWELITE GOLD has 22 pins: 16 dedicated digital pins and 6 shared digital-analog pins. This means that two pins are shared on TWELITE GOLD.
    • PIO0 is shared with DO0 (SPICLK) and DIO11.
    • PIO14 is shared with ADC2 (Vref) and DIO8.
      • In the AHI subset, you must set DIO8 to a digital port before using it.
  • While the DIO pins on TWELITE BLUE/RED were in a high-impedance, pull-up state at reset, the state of each pin on TWELITE GOLD is different. In the AHI subset, DIO0..19 and DO0,1 are set as input and pull-up at initialization, while ADC1,2 are set as analog inputs.

Pins that require careful handling

For details, refer to the JN518x datasheet.

  • PIO=5 (ISP_ENTRY): Similar to TWELITE BLUE/RED, when this pin is in a LOW state at reset, it enters a mode for firmware writing, etc.
  • PIO=4 (ISE_SEL): When ISP_ENTRY is enabled, the subsequent behavior is changed. If it is not set to a HIGH level during firmware writing, firmware cannot be written.
  • PIO=10, 11: These are mainly intended for I2C use, so they differ from other pins that can be used for GPIO. Specifically, there is no pull-up/down setting.

About Peripherals

Please refer to the documentation for the TWENETmwf (which organizes major functions through peripheral procedures) and TWENETcmpt libraries (intended for porting code using AHI).

1.2 - Startup Functions main(), WarmMain()

Startup functions main(), WarmMain()
This document describes the firmware startup functions.

Startup Functions main(), WarmMain()

This document describes the firmware startup and callback functions for TWELITE GOLD.

main(), WarmMain()

In TWELITE GOLD, the firmware starts from the main() function. A wake-up from sleep is handled by the WarmMain() function. Since these functions have a weak attribute, users can define their own versions.

__attribute__((weak)) int main(void);
__attribute((weak)) void WarmMain(void);

int main(void) {
    ToCoNet_vInit_Cold_Pre();
	ToCoNet_vBoard_Init(FALSE);
	ToCoNet_vInit_Cold(0, 0);
	ToCoNet_vMain(NULL);
}

void WarmMain(void)
{
    vAHI_OnWakeup_MW(FALSE);
    ToCoNet_vInit_Warm_Pre();
	ToCoNet_vBoard_Init(TRUE);
	ToCoNet_vInit_Warm(0);
	ToCoNet_vMain(NULL);
}
// source/twenet_main.c

Call flow for a cold boot (power-on, reset)

main()
  ToCoNet_vInit_Cold_Pre()    <= Memory initialization
                                 Call cbAppColdStart(FALSE) for TWENET C, init_cold() for MWX

  ToCoNet_vBoard_Init(FALSE)
    vAHI_RegEvMgr_MW()        <= Initialize mwf library
    BOARD_InitBootPins()
      BOARD_InitPins()        <= Initializes each pin in this function
    BOARD_BootClockRUN()      <= Clock initialization
    vAHI_FRWTStart_MW()       <= Start FRWT (WTIMER)
    G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
                              <= Preparation for on-chip temperature sensor acquisition
    GPIO_PortInit()           <= GPIO initialization
    checkIrqPending()         <= Clear interrupt status
    AES_Init()                <= AES encryption initialization
    __enable_irq()            <= Start interrupts

  ToCoNet_vInit_Cold()        <= TWENET initialization
                                 Call cbAppColdStart(TRUE) for TWENET C, setup() for MWX

  ToCoNet_vMain()             <= TWENET main loop

Call flow for a warm boot (wake-up from RAM retention sleep)

WarmMain()
  vAHI_OnWakeup_MW(FALSE)     <= Peripheral processing immediately after wake-up

  ToCoNet_vInit_Warm_Pre()    <= Call cbAppWarmStart(FALSE) for TWENET C, init_warm() for MWX

  ToCoNet_vBoard_Init(TRUE)
    BOARD_BootClockRUN()      <= Clock initialization
    vAHI_FRWTSetBootCount_MW() <= Save FRWT (WTIMER) wake-up count
    G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
                              <= Preparation for on-chip temperature sensor acquisition
    GPIO_PortInit()           <= GPIO initialization
    vAHI_OnWakeup_MW()        <= Wake-up processing
    checkIrqPending()         <= Clear interrupt status
    AES_Init()                <= AES encryption initialization
    __enable_irq();           <= Start interrupts

  ToCoNet_vInit_Warm()        <= TWENET initialization
                                 Call cbAppWarmStart(TRUE) for TWENET C, wakeup() for MWX

  ToCoNet_vMain()             <= TWENET main loop

Call flow for wake-up from RAM OFF sleep

main()
  vAHI_OnWakeupRamOff_MW(FALSE) <= Peripheral processing (checking DIO state)

  ToCoNet_vInit_Cold_Pre()    <= Memory initialization
                                 Call cbAppColdStart(FALSE) for TWENET C, init_cold() for MWX

  ToCoNet_vBoard_Init(FALSE)
    vAHI_RegEvMgr_MW()        <= Initialize mwf library
    BOARD_BootClockRUN()      <= Clock initialization
    vAHI_FRWTStart_MW()       <= Start FRWT (WTIMER)
    G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
                              <= Preparation for on-chip temperature sensor acquisition
    GPIO_PortInit()           <= GPIO initialization
	vAHI_OnWakeupRamOff_MW(TRUE) <= Peripheral processing (releasing GPIO RETENTION)
    checkIrqPending()         <= Clear interrupt status
    AES_Init()                <= AES encryption initialization
    __enable_irq()            <= Start interrupts

  ToCoNet_vInit_Cold()        <= TWENET initialization
                                 Call cbAppColdStart(TRUE) for TWENET C, setup() for MWX

  ToCoNet_vMain()             <= TWENET main loop

ToCoNet_vBoard_Init(bool_t)

__attribute__((weak)) void ToCoNet_vBoard_Init(bool_t bWarm);
// source/twenet_main.c

This function performs hardware initialization at startup. Since it has a weak attribute, you can define your own initialization procedures. Refer to the twenet_main.c source code for details.

This series of initialization steps includes the necessary corrections for projects generated by the MCUXpresso project wizard. For function structures and other details, please read through the code, referring to the SDK documentation.

If you need to perform unique hardware initialization, you’ll be modifying this section. Be aware that this is a sensitive part of the code, so careful modification and thorough testing are required.

ToCoNet_vInitCold(uint32)

void ToCoNet_vInit_Cold(uint32 flag, uint32 u32SysHz)

This function performs the TWENET initialization procedure.

ParameterDescription
flagStartup specification. Please use 0 for normal use.
u32SysHzSpecifies the SysTick timer frequency. Please use 0 for normal use.
If needed, specify a multiple of 1000.

ToCoNet_vInit_Warm()

void ToCoNet_vInit_Warm(uint32 flag)

This function performs the TWENET initialization procedure when waking up from sleep.

ParameterDescription
flagStartup specification. Please use 0 for normal use.

ToCoNet_vMain()

void ToCoNet_vMain(PR_TOCONET_MAIN_HOOK fp_hook)

This is the main loop for TWENET.

checkIrqPending()

static bool_t checkIrqPending();

uint64_t g_twenet_irq_bm_on_boot;
WEAK bool_t __twenet_irq_handler_pending_on_boot(int32_t);

This function saves and clears interrupt information that occurred during or after sleep, until this function is called.

  • Each bit of g_twenet_irq_bm_on_boot corresponds to an interrupt source (IRQ_Type) in the form (1uul << IRQ_Type).
  • The interrupt types are defined in typedef enum IRQn in JN5189.h.
  • Interrupts are cleared by calling NVIC_ClearPendingIRQ().
  • If a user defines the __twenet_irq_handler_pending_on_boot(int32_t IRQ_Type) function and the IRQ_Type interrupt is enabled, this function will be called. If the return value is FALSE, NVIC_ClearPendingIRQ(IRQ_Type) is executed. If it’s TRUE, nothing happens.

System Timer Cycle

You can set the SysTick timer cycle in the following ways:

  • Set it in the ToCoNet_vInitCold() function. This setting takes precedence.

  • Set G_TWENET_SYSTICK_HZ() in cbAppColdStart(FALSE).

  • If neither of the above methods is used, the value of sToCoNet_AppContext.u16TickHz will be used.

Please note the following:

  • The TWENET processing cycle (sToCoNet_AppContext.u16TickHz) has a maximum of 1000Hz.
    • The SysTick cycle is an integer multiple of sToCoNet_AppContext.u16TickHz.
  • The standard setting is SysTick = 1000Hz, sToCoNet_AppContext.u16TickHz = 1000Hz.
    • A semi-standard setting is SysTick = 2000Hz or 4000Hz, and sToCoNet_AppContext.u16TickHz = 1000Hz. This helps distribute the load by performing some background processing (like UART) outside of the TWENET cycle. This also allows for processing with a faster SysTick timer interrupt (see AppQAPI_SysTick_Hnd_Reg()).
    • Another semi-standard setting is SysTick = 250Hz, sToCoNet_AppContext.u16TickHz = 250Hz. This is used for power saving or when processing per timer is heavy, as the time per radio packet is about 2-5ms (transmission time after modulation and gaps between packets).
    • We do not confirm the operation of each API or our applications with semi-standard settings. If you need to use them, please perform thorough testing.

Initialization

G_TWENET_B_MAC_ALWAYS_RESET_ON_WAKE()

bool_t G_TWENET_B_MAC_ALWAYS_RESET_ON_WAKE()
  // Macro definition

Setting this variable to 1 will re-initialize the MAC layer when waking up from sleep. This re-initialization adds extra processing time (approximately 400µs at 32MHz).

  • Even with this option enabled, the pre-sleep process (saving the MAC layer state, about 100µs at 32MHz) will still be executed the same way as when the option is disabled.

1.3 - RAM Allocation

RAM allocation
Describes RAM allocation.

RAM Allocation

The SRAM area of TWWLIET GOLD is as follows.

BASETOP (End + 1)SIZE
SRAM110x0402_C0000x0403_000016KB
SRAM100x0402_80000x0402_C00016KB
SRAM90x0402_40000x0402_800016KB
SRAM80x0402_00000x0402_400016KB
SRAM70x0401_50000x0401_60004KB
SRAM60x0401_40000x0401_50004KB
SRAM50x0401_20000x0401_40008KB
SRAM40x0401_00000x0401_20008KB
SRAM30x0400_C0000x0401_000016KB
SRAM20x0400_80000x0400_C00016KB
SRAM10x0400_40000x0400_800016KB
SRAM00x0400_00000x0400_400016KB

TWENET defines the memory map as follows.

BASETOPSizePurposeRETBank Name
Application Use0x0400_0000Decided at compile time~64KBRequired for MMAC linkingSRAM0..3
Heap0x0401_5000
(Changeable)
0x0401_5C003KBHeap area (malloc, new)SRAM7
Unused0x0402_00000x0402_C00048KBUnused areaSRAM8, 9, 10
SRAM11
Unused0x0402_C0000x0402_F00012KBUnused areaSRAM11
Stack0x0402_F0000x0403_00004KBStack areaSRAM11

(BASE: Start Address, TOP: End Address + 1, RET: RAM Retention during sleep)

  • The application use area is a static memory range determined at compile time. The end address can be referenced with (uint32)&_end_fw_retention. When sleeping, the system is set not to retain unnecessary banks based on the end address.
  • The heap area is a region allocated by malloc() and the new operator. Generally, repeated allocation and deallocation of this area can lead to fragmentation issues, so you should be mindful of this when implementing your application. The default setting allocates memory to SRAM bank 7. However, the last 512 bytes of bank 7 are reserved by the microcontroller’s semiconductor specifications, and the subsequent 512 bytes are reserved by TWENET.
    • This area can be adjusted by writing HEAP_START=0x04014000; and HEAP_SIZE = 8192 - BANK7_RESERVE; in App_User_Defs.ld (placed directly in the build directory).
      • HEAP_START is the start address of the heap, and HEAP_SIZE is the allocated size. Here are some typical combinations:
        • 0x04014000, 8192-BANK7_RESERVE (7KB, BANK6-7)
        • 0x04012000, 16384-BANK7_RESERVE (15KB, BANK5-7)
        • 0x04010000, 24576-BANK7_RESERVE (23KB, BANK4-7)
        • 0x0, 0 (set the maximum area, i.e., from _end_fw_rentention to 0x04016000-BANK7_RESERVE, as the HEAP)
  • The unused areas are SRAM8, 9, and 10, each with 16KB.
  • The stack area is set to the last 4096 bytes of SRAM11 (0x0403_0000) by default.
    • You can change the size of this area by writing STACK_SIZE = 8192; in App_User_Defs.ld (placed directly in the build directory). You can also specify the end address, such as STACK_TOP = 0x04024000;.
    • Please check _vStackTop and __StackLimit in the map file created in the build directory.
    • This area is not retained during sleep.

I’ve translated the text and formatted it as plain text to avoid the issue you mentioned earlier.

Setting the Retention Area during Sleep

The TWENET library is pre-configured to properly retain the necessary SRAM banks for the application use and heap areas during sleep. However, depending on the design and implementation of your application, you may want to retain banks that are not normally held. To do this, you can set the corresponding bits for any additional banks you need in the global variable G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD() defined in the TWENETcmpt library.

For example, if you want to retain 32KB of banks 8 and 9, specify the following before calling ToCoNet_vSleep() in the TWENET C library or the_twelite.sleep() in the mwx library.

G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD() = PM_CFG_SRAM_BANK8_RET | PM_CFG_SRAM_BANK9_RET;

Note: Increasing the amount of retained SRAM will also increase the sleep current.

App_User_Defs.ld Configuration Examples

If not specified, the HEAP will be from 0x0401_5000 to 0x0401_5FE0, and the STACK will be from 0x0402_F000 to 0x0403_0000. Below are examples for the .../build/App_User_Defs.ld configuration.

  • To allocate the maximum possible HEAP, from _end_fw_retention to 0x0401_5FE0:
HEAP_START = 0;
HEAP_SIZE = 0;
  • To allocate HEAP in RAM6 and 7 (approx. 8KB):
HEAP_START = 0x04014000;
HEAP_SIZE = 8192 - BANK7_RESERVE;
  • To set the HEAP from _end_fw_retention to 0x0401_5000 and the STACK from 0x0401_5000 to 0x0401_5FE0. (This makes BANK8..11 from 0x0402_0000 to 0x0403_0000 an unused area):
HEAP_TOP = 0x04015000;
HEAP_START = 0;
HEAP_SIZE = 0;
STACK_TOP = 0x04015fe0;
STACK_SIZE = 4096-BANK7_RESERVE;

Note: If both HEAP_START and HEAP_SIZE are 0, you can set HEAP_TOP. In this case, HEAP_TOP cannot be set to a region equal to or greater than 0x0402_0000.

  • To allocate 64KB for the HEAP from 0x0402_0000 and move the STACK area to a region below 0x04015fe0:
HEAP_START = 0x04020000;
HEAP_SIZE = 0x10000;
STACK_TOP = 0x04015fe0;
STACK_SIZE = 4096-BANK7_RESERVE;

OneTime_Heap.c,h

TWENETutils provides a One Time Heap for sequential memory allocation without deallocation. This makes it easy to use unused areas.

#include <OneTimeHeap.h>
OTHEAP_tsContext scOTHeap;

void setup() {
    uint32 u32bytes;
    void *p;

    // Use the 16KB region from 0x0402_0000 to 0x0402_4000.
    OTHEAP_Init(&scOTHeap, 0x04020000, 0x04024000, NULL);

    Serial << crlf << "--- One Time HEAP ---";
    Serial << crlf << format("start %08x", (uint32)OTHEAP_pvGetRegionStart(&scOTHeap));
    Serial << crlf << format("top %08x", (uint32)OTHEAP_pvGetRegionTop(&scOTHeap));

    // Allocate 100 bytes
    u32bytes = 100;
    Serial << crlf;
    Serial << crlf << format("head %08x", (uint32)OTHEAP_pvGetHead(&scOTHeap));
    p = OTHEAP_pvAlloc(&scOTHeap, u32bytes, TRUE);
    		// p=0x0402_0004 (The area after the 4-byte header is available)
    Serial << crlf << format("alloc %dbytes [%08x->%08x)", u32bytes, (uint32)p, (uint32)p+u32bytes);
    if(p) Serial << crlf << format("next %08x", *(uint32*)((uint32)p - 4));
    		// The header is the address of the next block (0x0402_0068)

    // Allocate 10 bytes (actually 12 bytes because it's aligned to a 4-byte boundary)
    u32bytes = 10;
    Serial << crlf;
    Serial << crlf << format("head %08x", (uint32)OTHEAP_pvGetHead(&scOTHeap));
    p = OTHEAP_pvAlloc(&scOTHeap, u32bytes, TRUE);
    		// p=0x0402_006c
    Serial << crlf << format("alloc %dbytes [%08x->%08x)", u32bytes, (uint32)p, (uint32)p+u32bytes);
    if(p) Serial << crlf << format("next %08x", *(uint32*)((uint32)p - 4));
    		// The header is the address of the next block (0x0402_0078)

    // Free the last allocated block. The address of the freed block (p=0x0402_006c)
    p = OTHEAP_pvFreeLastBlock(&scOTHeap);
}

1.4 - About printf (Debugging, Serial Output)

About printf (Debugging, Serial Output)
This document describes printf (debugging, serial output).

About printf (Debugging, Serial Output)

printf Library

This is the printf() process used within the TWENET library. For more details, please refer to TWENETmuc/printf.

PRINTF for Debugging

The PRINTF() macro in the fsl library provided by NXP is used for debug output and is excluded from compilation during release. The TWENET library has also been adjusted to use PRINTF(), but it doesn’t have all the features of the fsl library.

  • The PRINTF() macro calls printf_() mentioned above.
  • Input macros like GETCHAR() are not supported.

With JN518x SDK 2.6.3 and 2.6.4, NewLib and NewLibNano show garbled or missing data in output and do not behave as expected (this is likely a buffering issue. RedLib does not show this problem, but it cannot be used in a mixed C/C++ project). For this reason, the PRINTF() macro has been changed to use the printf_() function within libTWENETmcu/printf.

SDK_DEBUGCONSOLE Definition

The behavior of the PRINTF() in your application will change based on the value of SDK_DEBUGCONSOLE.

ValueDescription
0Output is sent to the debug console (Semihosting). This process is very slow.
* To enable this output, you must set SDK_DEBUGCONSOLE=0 in the libTWENETmcu (Debug build), rebuild the library, and periodically call _putchar(-1) (approximately every 16ms) in your application code. (See SysTick_Handler() defined in the sample Samp_bare_MMAC)
1This is the setting for a Debug build. PRINTF uses the printf_ function (libTWENETmcu). If _putchar() is not redefined, SERIAL_bTxChar(0, c); is called. This is also the default setting for Debug builds of TWENETxxx libraries.
2This is the setting for a Release build. PRINTF is excluded from compilation, and printf_() outputs nothing. If you want to use printf_(), you must redefine _putchar(int). This is also the default setting for Release builds of TWENETxxx libraries.
  • The _putchar() in the libTWENETmcu library has a weak link specification. The _putchar() you define in your application code will take precedence.
  • To enable PRINTF() within the TWENETxxx library, you must set the same SDK_DEBUGCOSOLE definition in your application and rebuild the library.

About SWO

TWENETmcu/source includes code for SWO output. While we don’t officially support this feature, here’s a breakdown of its code and functionality:

  • Code related to SWO is defined with -DDEBUG and -DSERIAL_PORT_TYPE=1. When these are set, the PRINTF() output is adjusted to be sent to the SWO ITM (main/retarget_itm.c, main/retarget_putchar.c).
  • The SWO port is set to PIO14.
  • Debugging often fails to start when SWO is enabled. Keeping the ISP pin (PIO5) in a LOW state until just before the debugger starts can sometimes resolve this.

2 - TWENETmwf - Peripheral C++ Library

A library for handling microcontroller peripherals
This is a simplified C++ class for handling microcontroller peripheral procedures.

TWENETmwf - Peripheral C++ Library

This is a simplified C++ class for handling microcontroller peripheral procedures.

Pre-defined objects are available (e.g., mwf::the_i2c0 for I2C0), and you access their functions through these objects. The pre-defined objects are smart pointers using std::unique_ptr<>, and their actual instances are created upon first initialization.

This library’s pre-defined objects include procedures for before and after sleep, allowing you to perform pre-sleep and wake-up processing in a single step.

About Peripheral Objects

Many peripherals have integrated initialization and other procedures. This library manages them as class objects, from their creation to their destruction.

All class objects are smart pointers using std::unique_ptr<>. Before an object is created, it’s a nullptr, so no access is possible (it will likely cause a hang-up from a null pointer access). Always check for nullptr before using an object.

   if (the_adc) { // Check for nullptr first
      the_adc->enable((1UL << 0) | (1UL << 1));
      the_adc->start();
   }

Pre-defined Peripheral Class Objects

Object NameDescription
the_adcUse the Analog-to-Digital Converter (ADC)
the_gpioUse General Purpose IO (GPIO) interrupts. (The class object is not used if you don’t need interrupts)
the_i2c0Use the I2C bus. (I2C0 only)
the_ntagUse the EEPROM for NTAG
the_pwm[0..9]Use PWM0..9
the_rngRandom number generation library
the_spi1Use the SPI bus (SPI1 only)
the_wtimerUse the wake-up timer
the_wwdtUse the watchdog timer

About the Libraries

Object NameDescription
mwf_commonCommon definitions, base class definitions for peripheral objects
mwf_periph_commonCommon definitions, procedures for pin operations
mwf_periph_adcProcedures for using the ADC
mwf_periph_gintGeneral Purpose IO (GPIO) interrupts
mwf_periph_i2cUse the I2C bus. (I2C0 only)
mwf_periph_ntagUse the EEPROM for NTAG
mwf_periph_pwmUse PWM0..9
mwf_periph_rngRandom number generation library
mwf_periph_spiUse the SPI bus (SPI1 only)
mwf_periph_wtimerUse the wake-up timer
mwf_periph_wwdtUse the watchdog timer

About Namespaces

In principle, classes and functions are defined within the following namespaces:

  • mwf::
  • mwf::periph::

2.1 - mwf_common

mwf common definitions
Defines common definitions and base classes for peripheral classes.

mwf_common

Defines common definitions and base classes for peripheral classes.

Macros

BEGIN_CRITICAL, END_CRITICAL (Disable Interrupts)

#define BEGIN_CRITICAL { uint32_t __TWENET_regPrimask = DisableGlobalIRQ();
#define END_CRITICAL() EnableGlobalIRQ(__TWENET_regPrimask); }

// Example
extern volatile int critical_value;
void some_func() {
    ...
    // The following is a critical section
    BEGIN_CRITICAL
    {
       critical_value++;
    }
    END_CRITICAL();
}

These macros are used to set a disabled interrupt section. While they simply call DisableGlobalIRQ() and EnableGlobalIRQ(), they are defined as a macro similar to the do {...} while() construct to simplify the syntax, which can seem complex due to the need for a local variable.

In the example above, if critical_value is a value that might be changed by an interrupt handler, this procedure safely updates the value within the application’s processing.

  • This macro can only be used in C++ code.

Constants, Enumerations, etc.

enum class ID_SYSHAND

Defines IDs to identify peripheral class objects.

class sys_ev_handler

A high-level (abstract) class that defines an interface to standardize procedures for sleep and wake-up.

on_sleep()

Describes the peripheral’s procedures before sleep.

on_wakeup(bool init_2nd)

Describes the peripheral’s procedures to restore its pre-sleep state upon wake-up. This function is expected to be called twice.

  • When init_end is false, it is called at a very early stage after wake-up. It is primarily used for variable initialization, but no device re-initialization is performed here. The second time it is called, with true, it re-initializes devices and restores the pre-sleep state.
  • In TWENET, this is handled during the vAHI_OnWakeup_MW() call. The call order is as follows. For details, refer to twenet_main.c in TWENETmcu.
    • Call of the WarmMain() function (the first function called upon wake-up)
      • vAHI_OnWakeup_MW(FALSE)
        • The on_wakeup(false) of the mwf library object is called here
      • ToCoNet_vInit_Warm_Pre()
        • cbAppWarmStart(FALSE) (or init_warm() in mwx)
      • ToCoNet_vBoard_Init()
        • Initialization of the wireless microcontroller hardware (clock, etc.)
        • vAHI_OnWakeup_MW(TRUE)
          • The on_wakeup(true) of the mwf library object is called here
      • ToCoNet_vInit_Warm()
        • cbAppWarmStart(TRUE) (or setup() in mwx)
      • TWENET initialization
      • TWENET application loop

class sys_global_resource_handler<T>

A high-level class for managing initialization and destruction procedures when multiple instances of the same function are defined, such as I2C and PWM.

It is used when there are procedures that need to be performed only once upon initialization and procedures that need to be destroyed only after all instances have been used. (Even with these peripherals, this class may or may not be used depending on the implementation.)

The initialization and destruction procedures are performed based on a reference counter (passed from the constructor) that is updated whenever an object is created or destroyed.

  • sys_ev_handler is an abstract class, but this class uses CRTP.

init()

When the reference counter becomes 1 (i.e., when initialization is needed), T::global_init() is called.

  • This member function must be explicitly called from the peripheral class constructor.

deinit()

When the reference counter becomes 0, T::global_deinit() is called.

  • This member function must be explicitly called from the peripheral class destructor.

class sys_ev_manager

A collection class for managing peripheral class objects in a single place. However, it does not own the objects; it stores sys_ev_handler class pointers in a fixed array, using the ID specified by the ID_SYSHAND enumeration as an index.

Its main purpose is to perform on_sleep() and on_wake() procedures in a batch.

Since which peripheral class objects are created depends on the user’s program, calling if(the_pwm1) the_pwm1->on_sleep(); for every class object would be inefficient and link unnecessary code. Instead, it stores them as abstract objects of type sys_ev_handler and calls their virtual methods.

global_init_sysevmgr()

Creates the the_sys_ev_manager instance.

global_deinit_sysevmgr()

Destroys the the_sys_ev_manager instance.

reg_obj()

Registers a peripheral class object.

unreg_obj()

Deregisters a peripheral class object.

on_wakeup(bool init_2nd)

Executes on_wake() for all registered objects.

void on_sleep()

Executes on_sleep() for all registered objects.

Peripheral Class Definition Example

class timer_n_pwm :
      public mwf::sys_ev_handler // Base class
    , public mwf::sys_global_resource_handler<timer_n_pwm> // Base class (only if needed)
{
  using global_hdr = mwf::sys_global_resource_handler<timer_n_pwm>;
    // Define a shorthand because the name is long
  static uint32_t _global_init_ct;
    // Reference counter for sys_global_resource_handler

public:
  static void global_init_pwm(uint8_t u8_pwm_id, ...) { ... }
  static void global_deinit_pwm_manager(uint8_t u8_pwm_id) { ... }
     // Procedures for creating and destroying the actual instance of the_pwm?.

public:
  // Constructor
  timer_n_pwm(/* Constructor arguments */)
    : mwf::sys_ev_handler(/*ID*/ ,static_cast<sys_ev_handler*>(this))
    , mwf::sys_global_resource_handler<timer_n_pwm>(_global_init_ct)
  {
	global_hdr::init(); // Procedure for creating sys_global_resource_handler<>
  }

  // Destructor (defined as virtual because it inherits from an abstract class)
  virtual ~timer_n_pwm()
  {
    global_hdr::deinit(); // Procedure for destroying sys_global_resource_handler<>
  }

  // Implementation of the sys_ev_handler class
  virtual void on_sleep() { ... } // Called before sleep
  virtual void on_wakeup() { ... } // Called after waking up from sleep

  // Implementation of sys_global_resource_handler<>. Static member function.
  static void global_init(); // The very first initialization procedure
  static void global_deinit(); // The very last destruction procedure
};

...
uint32_t mwf::periph::timer_n_pwm::_global_init_ct; // The actual reference counter

The above is an excerpt from the definition of the PWM (mwf_periph_pwm.hpp) peripheral class. Most other classes do not use sys_global_resource_handler<>.

2.2 - mwf_periph_common - Peripheral common

mwf_periph_common - Peripheral common
Defines common peripheral definitions and pin operations.

mwf_periph_common - Peripheral common

include

#include "mwf_periph_common.hpp"

GPIO Operation Functions

These are static (inline) functions defined within struct pin that you can call.

set_pin_as_input()

static void set_pin_as_input(uint8_t pin, uint32_t param = 0)

Sets pin to an input state.

  • param is unused.

set_pin_as_output()

static void set_pin_as_output(uint8_t pin, uint32_t param = PORTOUT_INITSTATE_HIGH)

Sets pin to an output state.

  • If PORTOUT_INITSTATE_HIGH is specified for param, the pin will be set to a HIGH state when this function is called.

set_output()

 void set_output(uint8_t pin, uint8_t value)

Changes the output state of pin. If value is PORT_HIGH (1), it sets the pin to HIGH; if PORT_LOW (0), it sets it to LOW.

get_input()

 static uint8_t get_input(uint8_t pin)

Reads the state of pin when it is in an input state. The return value is PORT_HIGH (1) for HIGH and PORT_LOW (0) for LOW.

get_input_bm()

static uint32_t get_input_bm(uint32_t u32mask = 0x3FFFFF)

// Example
  uint32_t bm = get_input_bm((1ul << 0) | (1ul << 3));
  if (bm & (1ul << 3)) { ... } // If PIO3 is HIGH
  else { ... }                 // If PIO3 is LOW

Reads the input state of all pins as a bitmap.

  • The value of PIOn corresponds to the bit (1UL << n).
  • The values of pins not in an input state are undefined.

In the example, you specify a pin bitmap (u32mask) to get the state of input pins at once. For example, if you need the values for PIO0 and PIO3, you would specify (1ul << 0) | (1ul << 3).

The return value is also a bitmap of the input states. A HIGH level is represented by 1, and a LOW level by 0. For example, if PIO3 is HIGH, the 4th bit from the LSB will be 1.

set_output_bm()

static void set_output_bm(uint32_t u32mask, uint8_t value)

// Example
  set_output_bm((1ul << 0) | (1ul << 3), 0); // Sets PIO0 and 3 to LOW

Changes the output state for the pins corresponding to the bitmap specified by u32mask.

  • The value of PIOn corresponds to the bit (1UL << n).
  • If value is PORT_HIGH (1), it sets the output to HIGH; if PORT_LOW (0), it sets it to LOW.

In the example, you specify a pin bitmap (u32mask) to set the output state of multiple pins at once. For example, to set PIO0 and PIO3, you would specify (1ul << 0) | (1ul << 3). The value is 1 for a HIGH level and 0 for a LOW level.

PIN Operation Functions

These are static (inline) functions defined within struct pin that you can call.

static void __conf_digital()

static void __conf_digital(uint8_t pin, uint8_t func)

This function sets IOCON_PIO_FUNC(func) for the PIO register of the specified pin pin.

			IOCON->PIO[0][pin] =
							( 0
							| IOCON_PIO_FUNC(func) // SETFUNC (e.g. PWM is 0x04)
							| IOCON_PIO_MODE(0x00u) // 0x00:pullup
							| IOCON_PIO_DIGIMODE(0x01u)
							| IOCON_PIO_INPFILT_OFF
							);

static void conf_default()

static void conf_default(uint8_t pin)

This function reverts the pin to its default definition, as set in board/pin_mux.c within the TWENETmcu library.

static void __conf_gpio_input()

static void __conf_gpio_input(uint8_t pin)

This is for internal use. It sets pin pin as a GPIO input.

The user program should use set_pin_as_input().

static void __conf_gpio_output()

static void __conf_gpio_output(uint8_t pin, bool b_init_high = true)

This is for internal use. It sets pin pin as a GPIO output. If b_init_high is true, the initial output is a HIGH (Vcc) level; if false, it’s a LOW (GND) level.

The user program should use set_pin_as_output().

static void set_pullup()

static void set_pullup(uint8_t pin, uint8_t mode)

This function sets IOCON_PIO_MODE(mode) for the PIO register of the specified pin pin. This bit controls the pull-up behavior.

static void conf_pwmout()

static void conf_pwmout(uint8_t pin, bool b_enable)

This function uses __conf_digital() to set IOCON_PIO_FUNC(0x04) for the PIO register of the specified pin pin. This typically configures the pin for PWM output.

static void conf_adc_input()

static void conf_adc_input(uint8_t pin)

For pins PIO14..19, this function makes the following settings to configure them for ADC:

IOCON->PIO[0][pin] =
( 0
| IOCON_PIO_FUNC(0x00u) // FUNC_ALT0
| IOCON_PIO_MODE(0x00u) // 0x00:pullup
| IOCON_PIO_DIGIMODE(0x00u) // ANALOGUE
| IOCON_PIO_INPFILT_OFF
);

static void conf_sclN_pioM()

		static void conf_scl0_pio10() {
		    __conf_digital(10, 0x05);
		}

		static void conf_sda0_pio11() {
		    __conf_digital(11, 0x05);
		}

		static void conf_scl0_pio15() {
		    __conf_digital(15, 0x05);
		}

		static void conf_sda0_pio16() {
		    __conf_digital(11, 0x05);
		}

		static void conf_scl1_pio06() {
		    __conf_digital(06, 0x05);
		}

		static void conf_sda1_pio07() {
		    __conf_digital(07, 0x05);
		}

		static void conf_scl1_pio12() {
		    __conf_digital(12, 0x05);
		}

		static void conf_sda1_pio13() {
		    __conf_digital(13, 0x05);
		}

These are configuration functions for using the pins for I2C.

static void conf_uart1(uint8_t tx, uint8_t rx)

static void conf_uart1(uint8_t tx, uint8_t rx)

This function specifies the TXD pin of UART1 as tx and the RXD pin as rx.

  • You cannot set only one of the TXD or RXD pins with this function.

Others

struct ts_retention_context

struct ts_retention_context {
    uint32_t u32_bm_io;
    uint32_t u32_bm_set;
    void save();
    void restore();
};
static ts_retention_context s_retention_context;

static void retention_on_sleep()
static void retention_on_wake()

This is for internal use. It manages the processes and necessary data for retaining the GPIO output state during sleep.

static bool __b_check_swdbg_port(uint8_t pin)

static bool __b_check_swdbg_port(uint8_t pin)

This is for internal use. It determines whether a pin is used by the debugger during a debug session.

Behavior during Sleep

  • For pins whose GPIO output state has been set using set_pin_as_output(), the output state is maintained even during sleep. However, retention_on_sleep() and retention_on_wake() must be called appropriately. In TWENET, these functions are called during the pre-sleep and wake-from-sleep processes handled within the TWENETmcu and TWENETcmpt libraries.

2.3 - mwf_periph_adc - ADC

mwf_periph_adc - ADC
This is a peripheral object that summarizes the procedures for using the Analog-to-Digital Converter (ADC).

mwf_periph_adc - ADC

This is a peripheral object that summarizes the procedures for using the Analog-to-Digital Converter (ADC).

Code Example

The following example explicitly specifies the mwf:: namespace. To omit this, please write using namespace mwf;.

  • include
#include "mwf_periph_adc.hpp"
  • Initialization Procedure
// Create the the_adc class object
mwf::the_adc->global_init_adc_manager();

// Specify ADC input pins
mwf::pin::conf_adc_input(14);
mwf::pin::conf_adc_input(15);

// Initialization
mwf::the_adc->init();
  • ADC Start (One-shot)
// Specify channels
mwf::the_adc->enable(
     (1ul << mwf::adc::CH_0)
   | (1ul << mwf::adc::CH_1)
   | (1ul << mwf::adc::CH_VCC));

// Start ADC
mwf::the_adc->start(); // One-shot
while(!mwf::the_adc->available()) {} // Wait for completion by polling

// Get values
int16_t v_ch0 = mwf::the_adc->get_value_mv(mwf::adc::CH_0);
int16_t v_ch1 = mwf::the_adc->get_value_mv(mwf::adc::CH_1);
int16_t v_vcc = mwf::the_adc->get_value_mv(mwf::adc::CH_VCC);
  • ADC Start (Continuous)
// Specify channels
mwf::the_adc->enable(
     (1ul << mwf::adc::CH_0)
   | (1ul << mwf::adc::CH_1)
   | (1ul << mwf::adc::CH_VCC));

// Start ADC
mwf::the_adc->start(true); // Continuous

// Inside the application loop.
void loop() {
    if (mwf::the_adc->available()) {
        // Get values (to be executed periodically)
        int16_t v_ch0 = mwf::the_adc->get_value_mv(mwf::adc::CH_0);
        int16_t v_ch1 = mwf::the_adc->get_value_mv(mwf::adc::CH_1);
        int16_t v_vcc = mwf::the_adc->get_value_mv(mwf::adc::CH_VCC);

        ...
    }
}
  • Temperature Measurement
int32_t i32temp;
int16_t i16volt;

// Executes the process of turning on the internal sensor, waiting for stabilization, and performing ADC measurement (one time only).
mwf::the_adc->temp_capture(i32temp, i16volt, 0);

// i32temp is the temperature in degrees Celsius multiplied by 128. i16volt is in millivolts.
Serial << format("%dC %dmV", i32temp >> 7, i16volt);

class mwf::periph::adc

This section describes the main definitions for the the_adc class object.

Constant Definitions

static const uint8_t CH_MAX = 7;
static const uint8_t CH_0 = 0; // ADC0
static const uint8_t CH_1 = 1; // ADC1
static const uint8_t CH_2 = 2; // ADC2
static const uint8_t CH_3 = 3; // ADC3
static const uint8_t CH_4 = 4; // ADC4
static const uint8_t CH_5 = 5; // ADC5
static const uint8_t CH_VCC = 6; // VCC
static const uint8_t CH_TEMP = 7; // Internal temperature sensor (the acquisition method differs from normal ADCs)

These are the configuration definitions for the ADC channels.

struct config

struct config {
  uint8_t prescale;
};

This is a structure for setting configurations. It is passed as a parameter to init().

  • prescale: (Current version only supports DEFAULT_PRESCALE=6) A prescale value that determines the ADC conversion time. It sets (1ul << .prescale) to adc_config_t::clockDividerNumber defined in the fsl library and calls ::ADC_Init().

global_init_adc_manager() global_deinit_adc_manager()

static void global_init_adc_manager();
static void global_deinit_adc_manager();

These functions create and destroy the the_adc class object.

set_pin_as_adc()

static void set_pin_as_adc(uint8_t pin)

This function sets the specified pin number pin as an ADC input.

init() deinit()

void init(bool b_wait_init = true);
void deinit();

Initializes the ADC.

Setting b_wait_init to FALSE omits the ADC stabilization wait time (300ms). For details on handling the wait time, please refer to is_periph_enabled().

To initialize or re-initialize the ADC for internal temperature sensor acquisition, call init_for_temp_volt().

is_periph_enabled() force_periph_enabled() get_init_freerun_tick()

bool is_periph_enabled()
void force_periph_enabled()
uint32_t get_init_freerun_tick()

is_periph_enabled() returns true when the ADC has been initialized and the necessary waiting period has elapsed.

  • If the FRWT (Free Running Wake Timer) provided by the_wtimer is running, is_periph_enabled() will return false until the appropriate time has passed. You can get the tick count value at the time init() was called by calling get_init_freerun_tick().
  • If the FRWT is not running, the first call to is_periph_enabled() will incur a wait time of approximately 300 microseconds. To avoid this waiting process, you can call force_periph_enabled() immediately after calling init(). This forces the internal state to be treated as if the waiting period has already passed.

enable()

void enable(uint32_t chmask);

This function sets the ADC to an operational state. chmask is a bitmask of the channels to be converted. For example, if you want to target ADC0, ADC1, and VCC, you would specify (1ul << CH_0) | (1ul << CH_1) | (1ul << CH_VCC).

start() stop()

void start(bool b_cont = false);
void stop();

After calling enable(), you can start the ADC by calling start(). If b_cont is set to true, it will perform continuous conversion. Do not call start() if the ADC is already running.

To stop the conversion during continuous mode, call stop().

When the conversion is complete, a read of the_adc->available() will return true.

available()

bool available();

Returns true after the conversion is complete. After true is read, it returns false again.

is_started()

bool is_started();

Returns true if the ADC is currently running due to a call to start().

get_value()

uint16_t get_value(uint8_t ch);

Gets the 12-bit AD converted value for the channel specified by ch. Call this after the AD conversion is complete.

get_value_mv()

int16_t get_value_mv(uint8_t ch);

Gets the AD converted value in millivolts (mv) for the channel specified by ch. Call this after the AD conversion is complete.

global_init_device() global_deinit_device()

static void global_init_device();
static void global_deinit_device();

Performs the procedures for hardware initialization and termination of use.

Note: This is called internally from constructors, destructors, etc., and does not need to be explicitly called from the user application.

register_callback()

typedef void (*PFN_ADC_CALLBACK)(uint32_t, uint32_t);
void register_callback(PFN_ADC_CALLBACK pfn)

Specifies a callback function from within an interrupt handler.

The first parameter of the callback function is kADC_ConvSeqAInterruptFlag, and the second parameter is a bitmask of the channels that were converted.

Temperature Sensor

temp_capture()

bool temp_capture(
    int32_t& temp128th,
    int16_t& volt_mv,
    uint8_t times_adc_scaler = 0,
    bool b_power_on_temp_sensor = true)

Acquires the value of the on-chip temperature sensor. It also secondarily measures the supply voltage.

  • temp128th: Specifies the variable to store the temperature measurement result. The value is 128 times the value in degrees Celsius. The integer part can be calculated with temp128th >> 7, and the first decimal place with (10 * temp128th) >> 7.
  • volt_mv: Specifies the variable to store the voltage measurement result. The value is in millivolts [mV].
  • times_adc_scaler: Specifies a scaler value corresponding to the number of ADC repetitions. A value from 0 to 3 can be specified; 0 performs 1 AD conversion, 1 performs 2, 2 performs 4, and 3 performs 8, after which the values are averaged.
  • The return value is true on success and false on failure.

The following processes are performed implicitly:

  • If the temperature sensor is not ON, it is set to ON and the necessary waiting process is performed (see temp_power_on()).
  • The temperature sensor is turned OFF after execution.
  • It will fail if the ADC has not been initialized (init()).
  • If the device is not available after ADC initialization, it performs a waiting process (see is_periph_enabled()).

temp_get_capt_tick()

uint32_t temp_get_capt_tick()

This function returns the FRWT counter value from the last time the temperature was acquired.

temp_power_on(), temp_power_off()

void temp_power_on()
void temp_power_off()

These functions explicitly turn the temperature sensor ON/OFF.

If FRWT is enabled, you can shorten the waiting time by calling temp_power_on() in advance, as the function determines if the wait is complete based on the counter value.

temp_computation()

int32_t temp_computation(
	uint16_t adcout_vbat_lsb_sum8,
	uint16_t tsens_adcout_T_sum8,
	uint8_t nb_samples_actual = 1)

This is for internal use. It calculates the temperature from the ADC measurement values.

get_ctrl0_adc_reg_context()

class ctrl0_adc_reg;
ctrl0_adc_reg get_ctrl0_adc_reg_context(uint8_t mode, uint8_t tsamp)

// Example
   	if (auto rc = get_ctrl0_adc_reg_context(
			  0x0
			, 0x14
	)) {
        ; // This scope enables the (0x0, 0x14) setting. The original value is restored upon exiting the scope.
    }

This is for internal use. It temporarily changes the ADC configuration parameters.

class mwf::periph::adc (sys_ev_handler)

on_sleep()

Performs the ADC stop process.

on_wakeup()

If the ADC was initialized before sleep, it performs the initialization procedure (init()). You must execute enable() and start() again.

Others

About Operation in Continuous Mode

The conversion cycle is determined by the hardware. In the current version, the prescaler value is fixed.

Usage with AHI and mwx

The mwf::the_adc is used internally by the AHI and mwx libraries, so caution is required when using it directly.

  • If you are using the AHI library and also mwf::the_adc, please avoid calling any ADC-related procedures directly (e.g., vAHI_ApConfigure(), vAHI_AdcEnable(), vAHI_AdcStartSample() in adc.c that comes with App_Tweline).
  • If you are using the mwx library and also mwf::the_adc, please do not perform operations on the Analogue class object (e.g., Analogue.setup()).

2.4 - mwf_periph_gint - GINT(GPIO)

mwf_periph_gint - GINT(GPIO)
I implement general-purpose I/O input/output settings and I/O interrupts using GINT.

mwf_periph_gint - GINT(GPIO)

Implements general-purpose I/O input/output settings and I/O interrupts using GINT.

In TWENET, initialization and interrupt handling are processed within the TWENET library (TWENETcmpt). User programs typically do not need to call these functions directly.

include

#include "mwf_periph_gint.hpp"

class mwf::periph::gint

This is the definition for the the_gint class object. The creation of a the_gint class object is required to use pins for interrupt operations (including sleep interrupts). For implementation details, please refer to the “GINT-based DIO Interrupt Implementation” section below.

global_init_gint_manager() global_deinit_gint_manager()

static void global_init_gint_manager();
static void global_deinit_gint_manager();

These functions create and destroy the the_gint class object.

init_int() deinit_int()

void init_int(tpf_gpio_int_handler pf_callback, void *p_data = nullptr);
void deinit_int();

Initializes the GPIO interrupt. You can specify the interrupt handler (pf_callback) and a parameter (p_data) to be passed to the interrupt handler.

To stop the GPIO interrupt, call deinit_int().

pf_callback is defined as follows:

using tpf_gpio_int_handler = void(*)(uint32_t bm_now, uint32_t bm_changed, void *p_data);
  • bm_now: A bitmap corresponding to the current pin states.
  • bm_changed: A bitmap corresponding to the pins that have changed.
  • p_data: The p_data specified in init_int().

set_int_pins_bm()

void set_int_pins_bm(uint32_t u32mask_rising_edge, uint32_t u32mask_falling_edge);

This function specifies the pins to be targeted for interrupts.

The first parameter, u32mask_rising_edge, is a bitmap of the pins for which to detect a rising edge. The second parameter, u32mask_falling_edge, is a bitmap of the pins for which to detect a falling edge.

It is also possible to set both rising and falling edges.

gint_poll()

void gint_poll();

Performs the same process as the interrupt handler.

Calling this function periodically from a 1ms system timer, for example, can sometimes alleviate the limitations described in the “GINT-based DIO Interrupt Implementation” section below (where a port state might change after being read in the interrupt handler and that change is not processed). In most cases, this process is not necessary.

set|unset|get_opt_stop_int_when_changed()

void set_opt_stop_int_when_changed();
void unset_opt_stop_int_when_changed();
bool get_opt_stop_int_when_changed();

These functions stop the interrupt operation for a pin after a state change is detected, which helps mitigate the effects of mechanical button bouncing, etc.

Specifically, when a pin’s state changes and an interrupt occurs, the pin that was determined to have changed within the interrupt handler is temporarily excluded from being an interrupt pin.

*Since the GINT interrupt mechanism cannot determine which pin caused the interrupt, the state of the pins is read immediately after the interrupt handler executes and compared with the previous state to detect a change.

If this option is set, you should call reactivate_in_pins() after a pin change has been detected and the pin state has stabilized.

reavtivate_int_pins()

void reavtivate_int_pins();

This function resumes interrupts for pins that were temporarily stopped. Refer to the set_opt_stop_int_when_changed() option setting for details.

get_gint_context()

gint_context& get_gint_context();

This function accesses the internal structure. It is used to get the bitmaps of the configured rising and falling edge pins (.bm_rise and .bm_fall) and the wake-up cause pin during sleep (.bm_wake).

_gint_update()

    std::tuple<uint32_t, uint32_t> _gint_update(
			  uint32_t u32mask_rising_edge = 0x80000000
			, uint32_t u32mask_falling_edge = 0x80000000);

(Internal function, not to be used from user programs)

  1. Configures the interrupt pins.
  2. Determines and updates the pin state changes (if u32mask_rising_edge and u32mask_falling_edge are 0x80000000). If a state change occurs, it calls the callback function registered with init_int().

gint_handler()

static void gint_handler();

(This is an internal function and should not be used from user programs)

The GINT interrupt handler.

_gint_get_changed_by_specified_edge()

 uint32_t _gint_get_changed_by_specified_edge(uint32_t bm_cur, uint32_t bm_changed)

(This is an internal function and should not be used from user programs)

This function extracts the pins that match the specified rising or falling edge conditions from the changed pins. The calculation uses the current bitmap state (bm_cur) and the changed pins (bm_changed).

class mwf::periph::gpio (sys_ev_handler)

on_sleep()

Stops the interrupt if GINT is active.

In TWENET, vAHI_DioOnSleep_MW() sets the interrupt-configured pins (configured via this library using set_int_pins_bm()) for wake-up from sleep. Note that you cannot specify rising or falling edges for wake-up from sleep.

on_wakeup()

If woken up by a GPIO interrupt, this function saves the pin information corresponding to the wake-up cause (PMC->WAKEIOSOUCE).

Also, if interrupt pins were specified before sleep, it re-initializes GINT so that the interrupt operation resumes.

GINT-based DIO Interrupt Implementation

Because the PINT functionality is limited to a maximum of 4 ports, a similar function has been implemented using GINT (Group INT). Since GINT is not an interrupt detection mechanism focused on specific pins like PINT, there are some limitations. As the TWENET library does not use PINT, if the limitations of the GINT implementation are problematic, you should consider implementing a PINT-based solution.

Limitations

  • Signals that change state again shortly after a state change, such as noise or short pulses, may lead to unexpected behavior (e.g., missed detections).
    • It is assumed that the same state will be maintained for a certain period after a state change.
      • Due to GINT’s constraints, a very short pulse can be detected by the GINT interrupt, but it is not possible to determine which pin has changed. For details, please refer to the “Implementation” section below.
      • If a state is maintained for about 10µs after an edge, the GINT edge can be re-configured, so it is expected to work in principle. However, for safety, a duration of about 30-50µs (equivalent to one interrupt handler execution time) is recommended as a guideline for the state to remain the same.
    • When detecting a falling edge from a GND state, and conversely, when detecting a rising edge from a VCC state, missed detections are more likely to occur in principle.
    • For signals containing chattering or noise, use the option to temporarily disable interrupts for the pin upon the first interrupt occurrence (vAHI_DioInterruptDisablePinsIntWhenChanged_MW(TRUE); or mwf::the_gpio->set_opt_stop_int_when_changed();). After waiting for a certain period for the pin state to stabilize, call vAHI_DioInterruptReavtivate_MW(); or mwf::the_gpio->reavtivate_int_pins();.
    • Although not necessary in most cases, calling the_gpio->gint_poll() periodically (e.g., from a 1ms system tick) can increase interrupt overhead but may mitigate the effect of missed detections.

Note: The values mentioned are based on a CPU operating at 32MHz.

Note: If you wish to use the semiconductor’s functions directly, please do so without initializing this library and use GINT or PINT directly.

Implementation

GINT’s original purpose is to treat multiple pins as a group and generate an interrupt when there is a change in the group as a whole, not to be aware of the state of individual pins.

It is implemented as follows:

  • The current pin state is read, and the GINT detection edge is set (falling for HIGH, rising for LOW) to enable the interrupt.
  • A GINT interrupt occurs (a change on one of the pins triggers the interrupt handler).
    • The state of each pin is read to detect which pins have changed.
    • The GINT detection edge setting is reconfigured to match the newly read pin states.
    • The application is notified (via a callback) of the pins that have changed.

Note: The interrupt handler will be called again immediately afterward.

Note: The values and numbers shown are based on a library code under development, with two target pins for detection and a microcontroller operating at 32MHz.

When two pins go to a LOW level at the same time

The interrupt handler is called 1.5µs after the interrupt occurs. The pre-interrupt processing (reading pins and reconfiguring the detection edge) takes up to 6.6µs. After that, the application is notified (via the interrupt callback), which takes until 22µs after the interrupt occurred.

The interrupt occurs one more time (this is thought to be the behavior of the GINT hardware). In the second interrupt, no state change is usually detected, but it may suppress exceptional missed detections.

  • Horizontal axis: (10µs/DIV)
  • Pink: From the start of the interrupt handler until the GINT detection edge is reconfigured (1V/div)
  • Cyan/Yellow: Input signal (2V/div)

If another pin changes during the interrupt handler, example 1

In this example, another pin (cyan) changed during the first part of the interrupt handler, so it was processed consistently within the first handler. The behavior is the same as the simultaneous change mentioned above. The changes of both the yellow and cyan pins are communicated to the application in the first interrupt.

  • Horizontal axis: (10µs/DIV)
  • Pink: From the start of the interrupt handler until the GINT detection edge is reconfigured (2V/div)
  • Blue: From the start to the end of the interrupt handler (2V/div)
  • Cyan/Yellow: Input signal (5V/div)

If another pin changes during the interrupt handler, example 2

In this example, another pin (cyan) changes during the interrupt handler, but since the change occurs after the detection edge has been reconfigured, an interrupt occurs immediately afterward. A third handler is executed after the second handler finishes. The change of the yellow pin is communicated to the application in the first interrupt, and the change of the cyan pin is communicated in the second interrupt.

  • Horizontal axis: (10µs/DIV)
  • Pink: From the start of the interrupt handler until the GINT detection edge is reconfigured (2V/div)
  • Blue: From the start to the end of the interrupt handler (2V/div)
  • Cyan/Yellow: Input signal (5V/div)

2.5 - mwf_periph_i2c - I2C

mwf_periph_i2c - I2C
This is a peripheral object that summarizes the procedures for using the I2C bus.

mwf_periph_i2c - I2C

This is a peripheral object that summarizes the procedures for using the I2C bus.

Code Example

The example below explicitly specifies the mwf:: namespace. If you want to omit it, write using namespace mwf;.

  • Include
#include "mwf_periph_i2c.hpp"
  • Initialization
// create instance of the_i2c0.
if (!mwf::the_i2c0) {
  mwf::i2c::global_init_i2c0_manager();
}

// I2C device init
mwf::the_i2c0->init();

// write 2bytes (e.g. kick sensor capturing)
const uint8_t cmd1[] = { 0x60, 0x9C };
if (!mwf::the_i2c0->write_blocking(0x70, cmd1)) return false;

// wait (e.g. wait sensor data conversion.)
CLOCK_uDelay(1000*30); // wait some for sensor data conversion.

// read 6 bytes (e.g. read the sensor data.)
uint8_t data[6];
mwf::the_i2c0->read_blocking(0x70, data);
  • Read (Blocking API)
// write 2bytes (e.g. kick sensor capturing)
const uint8_t cmd1[] = { 0x60, 0x9C };
if (!mwf::the_i2c0->write_blocking(0x70, cmd1)) return false;

// wait (e.g. wait sensor data conversion.)
CLOCK_uDelay(1000*30); // wait some for sensor data conversion.

// read 6 bytes (e.g. read the sensor data.)
uint8_t data[6];
mwf::the_i2c0->read_blocking(0x70, data);

In this example, a command to start data acquisition is sent to the sensor, and after waiting for the sensor’s operation time (the time required by the sensor), data acquisition is performed.

  • Reading (Non-blocking API)
// write 2bytes (e.g. kick sensor capturing)
const uint8_t cmd1[] = { 0x60, 0x9C };
if (!mwf::the_i2c0->write(0x70, cmd1)) return false;
while(!mwf::the_i2c0->available()); // waiting for completion of write operation.

// wait (e.g. wait sensor data conversion.)
CLOCK_uDelay(1000*30); // wait some for sensor data conversion.

// read 6 bytes (e.g. read the sensor data.)
uint8_t data[6];
mwf::the_i2c0->read(0x70, data);
while(!mwf::the_i2c0->available()); // waiting for completion of read operation.

These are the same write() and read() functions as the blocking API, but with the non-blocking API, they return immediately without waiting for the data transmission to complete. You must either wait a sufficient amount of time or wait for the_i2c0->available() to become true before performing subsequent operations (in the example above, polling is performed immediately after write()/read(), so there is no difference in usage from the blocking API).

class mwf::periph::i2c

Describes the procedures for using I2C.

*Note: In the current implementation, only the the_i2c0 class object, which uses I2C0, is available.

E_PIN_CONF

enum class E_PIN_CONF : uint8_t {
    NODEF = 0,   // Not specified
    PRIMARY = 1, // Primary assignment (PIO10/11)
    ALT = 2      // Alternate assignment (PIO15/16)
};
// Type for assignments, comparisons, etc. between enum class and int types.
using wE_PIN_CONF = mwf::enum_wapper<E_PIN_CONF>;

This is an enumeration for specifying pin assignments.

global_init_i2c0_manager(), global_deinit_i2c0_manager()

static void global_init_i2c0_manager(wE_PIN_CONF pin_conf = E_PIN_CONF::PRIMARY);
static void global_deinit_i2c0_manager();

These functions create and destroy the the_i2c0 class object.

During creation, you can specify the pin configuration with pin_conf as either E_PIN_CONF::PRIMARY (value 0, SCL=PIO10, SDA=PIO11) or E_PIN_CONF::ALT (value 1, SCL=PIO15, SDA=PIO16). The pin initialization is performed when init() is called.

(eE_PIN_CONF is a wrapper class for enum class E_PIN_CONF, with definitions for assignment and comparison with int types.)

init(), deinit()

void init(uint32_t clock_freq = 0, wE_PIN_CONF pin_conf = E_PIN_CONF::NODEF);
void deinit();

Initializes the I2C bus and performs the termination procedure. During initialization, clock_freq is provided as a parameter; if it is 0, the default clock of 100kHz is selected; otherwise, clock_freq[Hz] is specified as the frequency.

If pin_conf is not specified (E_PIN_CONF::NODEF value 0), the pins specified in global_init_i2c0_manager() are used. If pin_conf is specified, the pins are initialized with that setting. Thereafter, if this parameter is omitted, the last specified pins will be used.

write_blocking(), write()

bool write_blocking(uint8_t addr, const uint8_t* buf, unsigned size);
template <unsigned N> bool write_blocking(uint8_t addr, const uint8_t (&buf)[N]);

bool write(uint8_t addr, const uint8_t* buf, unsigned size);
template <unsigned N> bool write(uint8_t addr, const uint8_t (&buf)[N]);

These functions write data to the I2C bus.

write_blocking() is a blocking function that waits for the write to complete. write() is a non-blocking function that returns immediately without waiting for the write to finish. When the write is complete, .available() will be true.

addr is the 7-bit I2C bus address, buf is the data to be written, and size is the number of bytes to write. If buf is a fixed-size array of size N, N bytes are written.

read_blocking(), read()

bool read_blocking(uint8_t addr, uint8_t* buf, unsigned size);
template <unsigned N> bool read_blocking(uint8_t addr, uint8_t(&buf)[N]);

bool read(uint8_t addr, uint8_t* buf, unsigned size);
template <unsigned N> bool read(uint8_t addr, uint8_t(&buf)[N]);

These functions read data from the I2C bus.

read_blocking() is a blocking function that waits for the read to complete. read() is a non-blocking function that returns immediately without waiting for the read to finish. When the read is complete, .available() will be true.

addr is the 7-bit I2C bus address, buf is the data storage buffer, and size is the number of bytes to read. If buf is a fixed-size array of size N, N bytes are read.

_transfer()

bool _transfer(OPT op, uint8_t addr, uint8_t* buf, unsigned size);

This function performs non-blocking read/write operations. op specifies whether to read or write, addr is the I2C bus address, buf is the buffer for reading or writing, and size is the number of bytes to read or write.

_transfer_blocking(), _start_blockin(), _stop_blocking()

bool _transfer_blocking(OPT op, uint8_t* buf, unsigned size, bool sendStop = false)
bool _start_blocking(OPT op, uint8_t addr);
bool _stop_blocking();

These functions are adjusted for the mwx library to perform blocking read/write procedures. Call _start_blocking(), _transfer_blocking() as many times as needed, and then _stop_blocking(). The sendStop parameter in _transfer_blocking() can be set to true on the last transfer to appropriately send a STOP signal.

available()

bool available();

This function determines if a transfer has finished when using the non-blocking API. It returns true when the transfer is complete.

is_success()

bool is_success();

When using the non-blocking API, this function returns whether the last transfer was successful. A return value of true indicates that the transfer was successful.

class mwf::periph::i2c (sys_ev_handler)

on_sleep()

As a procedure before sleep, it terminates the use of the I2C device.

on_wakeup()

If the device was initialized (init() call) before sleep, init() is called again to re-initialize it.

2.6 - mwf_periph_ntag - NTAG

mwf_periph_ntag - NTAG
This describes the procedures for reading and writing to the EEPROM of the short-range wireless communication (NTAG) controller (NT3H2211) built into the chip.

mwf_periph_ntag - NTAG

This describes the procedures for reading and writing to the EEPROM of the short-range wireless communication (NTAG) controller (NT3H2211) built into the chip. The controller is connected via I2C, but it does not use mwf::periph::i2c.

This procedure allows reading and writing to a 1KB area (NT3H2211 I2C block addresses 64-127).

Code Example

#include "mwf_periph_ntag.hpp"

void func() {
    // create the_ntag class object.
    if (!mwf::the_ntag) {
      mwf::ntag::global_init_ntag_manager();
    }

    // initialize
    mwf::the_ntag->init();

    // write 128bytes
    uint8_t xfer1[128];
    for (unsigned i = 0; i < 128; i++) xfer1[i] = i;
    mwf::the_ntag->write_user_area(0x00, xfer1);

    // read 128bytes
    uint8_t xfer2[128];
    mwf::the_ntag->read_user_area(0x00, xfer2);
}

class mwf::periph::ntag

global_init_ntag_manager(), global_deinit_ntag_manager()

static void global_init_ntag_manager();
static void global_deinit_ntag_manager();

These functions create and destroy the the_ntag class object.

init(), deinit()

void init();
void deinit();

These functions perform initialization and termination procedures for device access. Initialization (init()) includes a waiting period of 300µs.

write_user_area()

bool write_user_area(uint16_t addr, const uint8_t *p, uint16_t len);
template <unsigned N> bool write_user_area(uint8_t addr, const uint8_t (&buf)[N]);

This function writes a byte sequence to the EEPROM user area.

addr specifies the starting address from 0 to 1023. p or buf is the buffer for the data to be written. len or N is the number of data bytes.

read_user_area()

bool read_user_area(uint16_t addr, uint8_t *p, uint16_t len);
template <unsigned N> bool read_user_area(uint8_t addr, const uint8_t (&buf)[N]);

This function reads a byte sequence from the EEPROM user area.

addr specifies the starting address from 0 to 1023. p or buf is the destination buffer for the data to be read. len or N is the number of data bytes.

class mwf::periph::ntag (sys_ev_handler)

on_sleep()

Performs the termination procedure before sleep.

on_wakeup()

If the device was initialized before sleep, it re-initializes it. If re-initialization is not required, call deinit() before sleeping.

2.7 - mwf_periph_pwm - PWM, Timer

mwf_periph_pwm - PWM, Timer
This is a peripheral object that summarizes the procedures for using PWM and timers.

mwf_periph_pwm - PWM, Timer

This is a peripheral object that summarizes the procedures for using PWM and timers.

The the_pwm[] class object is used for operations. Although the class object is defined as an array, you can use PWM0 (the_pwm[0]) to PWM9 (the_pwm[9]).

PWM10 is not supported by this library.

Code Example

The example below explicitly specifies the mwf:: namespace. If you want to omit it, write using namespace mwf;.

#include "mwf_periph_pwm.hpp"

// in some func.
void func() {
	// create instance of PMW0.
	if (!the_pwm[0]) { // The class object of PMW0 is the_pwm[0].
		timer_n_pwm::global_init_pwm_manager(
		  0,   // PWM0
		  timer_n_pwm::PIN::ALT,
		       // The timer_n_pwm::PIN::PRIMARY will assign smaller PIO number PIO0 from PWM0,
		       // or conversely, timer_n_pwm::PIN::::ALT assigns PIO12.
		  true // set true to enable PWM output.
	  );
	}

	// set `x' as an alias of the_pwm[0].
	auto& x = the_pwm[0];

	// Init the device
	//x->init(); // not necessary, the constructor will call init() implicitly.

	// if needs INT, set true. (default: false)
	x->set_int_enabled(true);

	// set prescale
	x->set_prescale(6); // 0:32MHz 1:16Mhz 2:8Mhz ...

	// set polarity: if false, set HIGH while active state. (default: false)
	x->set_invert(false);

	// set cycle
	// note: 500Hz Duty 10% (Hi 0.2ms, Low 1.8ms)
	x->set_cycle(
		   100 // conut for an active state (HIGH)
		,  999 // count for a period (+1)
	);

	// start PWM out
	x->restart();
}

// INT handler (call set_int_enabled() before restart())
// note: if TWENETcmpt library is not linked, the IRQ handlers for PWM1..9 shall be defined.
extern "C" void PWM0_IRQHandler(void) {
  	... // some procedures.
 	PWM_ClearStatusFlags(PWM, kPWM_Pwm0);
}

class mwf::periph::timer_n_pwm

global_init_pwm_manager()

static void global_init_pwm_manager(
    		  uint8_t u8_pwm_id
			, uint8_t u8_pin_number
			, bool b_output_enabled = true
		 );

static void global_init_pwm_manager(
    		  uint8_t u8_pwm_id
    		, PIN e_pin
			, bool b_output_enabled = true
		);

To construct the the_pwm[] class object, you specify the PWM number and the corresponding pin.

The PWM number is specified as u8_pwm_id. Each PWM has two available pins (PWM5 only has PIO16). In this API, you can either specify the pin number directly as u8_pin_number or specify the lower pin number (timer_n_pwm::PIN::PRIMARY) or the other pin number (timer_n_pwm::PIN::ALT) from the available pins.

The behavior is undefined if you specify a conflicting number.

global_deinit_pwm_manager()

static void global_deinit_pwm_manager(uint8_t u8_pwm_id);

This function destroys the constructed the_pwm[] class object.

set_pwm_output()

void set_pwm_output(bool_t b_enable);
bool get_pwm_output();

Changes the output state of the pin. If b_enable is true, the output is enabled, and the hardware pin settings are also changed. If it is false, the pin is set to the default setting (conf::pin::conf_default()).

  • This function can be called while PWM is active.
  • If the output is already set by a parameter in global_init_pwm_manager(), there is no need to call this function again.

set_int_enabled()

void set_int_enabled(bool_t b_enable);
bool get_int_enabled();

This function sets the interrupt to be enabled or disabled. If b_enable is true, the interrupt is enabled; if it is false, it is disabled.

  • This function can be called while PWM is active.
  • Please refer to the “Interrupt Handler” section below.

set_prescale(), set_divisor()

void set_prescale(uint8_t u8_prescale);
void set_divisor(uint16_t u16_div);

These functions set the prescale for PWM control, which determines the PWM control frequency.

  • These functions can be called while PWM is active.
  • If set_prescale(u8_prescale) is specified, the control frequency is determined as follows: 0: 32MHz, 1: 16MHz, 2: 8MHz, …, 9: 62500Hz, 10: 31250Hz. Values 11 and above are undefined (assert in debug mode).
  • If set_divisor(u16_div) is specified, the control frequency is (32MHz / u16_div). The valid range is 1 to 1024, and the behavior is undefined if a value outside this range is specified.
  • The PWM period and duty cycle are determined by the parameters of set_cycle().
    • For example, if set_prescale(2) is specified, the control frequency is fb=8MHz. With this setting, if set_cycle(2, 10) is specified, the PWM period is fb/10 = 800kHz, and the pulse width is 2/fb = 2/8000000 = 250ns.

set_cycle()

void set_cycle(uint16_t ct_comp, uint16_t ct_period);
uint16_t get_period_val(); // get total period count
uint16_t get_comp_val();   // get active region count

This function specifies the count values that determine one PWM cycle and the active period within it. The pin value changes during the active period, and an interrupt is generated at its end.

ct_comp is the count for the active period, and ct_period is the total count for one cycle. For example, if ct_comp is 100 and ct_period is 1000, the PWM period will be 1000 counts at the PWM control frequency. With set_invert(false), the behavior will be HIGH for 100 counts and LOW for the remaining 900 counts.

  • This function can be called while PWM is active.
  • ct_comp is valid from 0 to ct_period - 1. The upper limit for the active period ratio is (ct_period - 1) / ct_period, and it cannot be set to 100%. set_duty() takes a 100% setting into consideration.
  • The count value for one cycle, ct_period, is set as ct_period - 1 in the hardware register. Please be careful not to specify the hardware register value directly in this function.

set_duty()

void set_duty(uint16_t u16duty, uint16_t u16duty_max = 1000);

This function sets the PWM duty cycle.

  • You must have previously used set_cycle() to specify the count for one PWM cycle. If you omit this step, u16duty_max is set as the PWM cycle count.
  • The active period is set to a ratio of u16_duty/u16duty_max of the total cycle. For example, if set_duty(100) is specified, the active period is 10% of the cycle.
  • If u16duty is set to the same value as u16duty_max, the entire cycle becomes active, resulting in a HIGH level if the default non-inverted waveform output (set_invert(false)) is used. (Due to hardware constraints, the active period cannot be set to the entire cycle. Internally, the waveform output register is inverted, and the active period is set to 0.)
    • For this reason, if you call set_cycle() after setting the duty cycle to 100% with set_duty(), the waveform will be inverted. Please be careful not to mix their usage.

set_invert()

void set_invert(bool_t b_invert);
bool get_invert();

This function inverts the output waveform. When set to false (default), the active period is at a HIGH level. When set to true, it is at a LOW level.

start(), stop()

void start();
void restart();
void stop();

These functions start, restart (with current settings), and stop the PWM output.

  • When stopped with stop(), the pin state is LOW if set_invert(false) (default) is set, and HIGH if set_invert(false) is set.

class mwf::periph::timer_n_pwm (sys_ev_handler)

sys_ev_handler is a procedure for before and after sleep.

on_sleep()

The PWM execution state is saved, and the pin state is returned to the default setting during sleep.

on_wakeup()

The state saved before sleep is restored.

class mwf::periph::timer_n_pwm (sys_global_resource_handler)

The sys_global_resource_handler<T> (where T is the timer_n_pwm class) is a procedure for performing necessary initialization and termination only once for multiple PWM class objects. It is used implicitly internally.

  • The constructor and on_wakeup() call sys_global_resource_handler<T>::init().
    • If it’s the first instance created, it calls T::global_init().
  • The destructor and on_sleep() call sys_global_resource_handler<T>::deinit().
    • If it’s the last instance to be destroyed, it calls T::global_deinit().

T::global_init()

Calls ::PWM_Init() to initialize the PWM.

T::global_deinit()

Calls ::PWM_DeInit() to terminate the use of the PWM.

Interrupts

When set_int_enabled(true) is set, an interrupt is generated at the end of the active period. The interrupt handler is provided by the system and is named PWMn_IRWHandler() (where n is the PWM channel).

              Interrupt
                 V                 Interrupt
                 V
Vcc    +----+                +----+
       |    |                |    |                t
GND----+    +----------------+    +-------------->
       <----> Active Period
       <--------------------> One PWM Cycle

The interrupt handler must be explicitly defined. The handler function that needs to be defined changes depending on whether the TWENETcmpt library is linked.

  • If TWENETcmpt is linked, only define the handler for the PWM channel you are using.
  • If TWENETcmpt is not linked, you must explicitly define interrupt handlers for all PWM channels from PWM0 to PWM9, even if you are not using an interrupt.

Interrupt Handler

When using TWENET, interrupts are converted into an interrupt function (cbToCoNet_u8HwInt()) and an event (cbToCoNet_vHwEvent()).

If you want to define your own interrupt handler, you must define PWNn_IRQHandler() separately. The following example shows a definition for PWM1. When you define your own, TWENET interrupts and events will not be generated.

// note: in c file, `extern "C"' should be removed.
extern "C" void PWM1_IRQHandler(void) {
    PWM_ClearStatusFlags(PWM, kPWM_Pwm1);
}

2.8 - mwf_periph_rng - TRNG

mwf_periph_rng - TRNG
This is a peripheral object that summarizes the procedures for using the chip’s built-in random number generation hardware.

mwf_periph_rng - TRNG

This implements the_rng, a peripheral object that summarizes the procedures for using the chip’s built-in random number generation hardware.

With TWENET, this is used implicitly, so no initialization procedure is required in the user’s program.

Code example

if (!mwf::the_rng) {
    mwf::rng::global_init_rng_manager();
    mwf::the_rng->init();
}

uint32_t val = mwf::the_rng->random();

class mwf::periph::rng

global_init_rng_manager(), global_deinit_rng_manager()

static void global_init_rng_manager();
static void global_deinit_rng_manager();

These functions create and destroy the the_rng class object. The class object is automatically initialized upon creation, and random values can then be obtained.

random()

uint32_t random()

Returns a random value.

class mwf::periph::rng (sys_ev_handler)

on_sleep()

Performs the TRNG stop procedure.

on_wakeup()

Performs the TRNG startup procedure.

2.9 - mwf_periph_spi - SPI

mwf_periph_spi - SPI
This is a class object for using the SPI bus.

mwf_periph_spi - SPI

This implements the_spi1, a class object for using the SPI bus.

  • SPI0 support is not included in the code.
  • Some definitions are included for non-blocking operations, but only blocking APIs are available in the current version.

Code Example

#include "mwf_periph_spi.hpp"

void func_spi_init() {
    if (!mwf::the_spi1) {
        mwf::spi::global_init_spi1_manager();
        Serial << crlf << "the_spi1 constructed.";
    }

    mwf::spi::config conf{};
    conf.baud = 4000000UL; // 4MHz
    conf.bits = 8;         // 8bit
    conf.dir  = mwf::spi::E_SPI_DIR::MSB_FIRST;
    conf.mode = mwf::spi::E_SPI_MODE::MODE_3_INV_RISE;
    conf.pin_ssel[0] = mwf::spi::E_PIN_SSEL::SSEL0_PIO3;
    conf.pin_ssel[1] = mwf::spi::E_PIN_SSEL::SSEL1_PIO16;
    mwf::the_spi1->init(conf);
}

void func_spi_transfer() {
    uint8_t tx[16] = { 0xa5, 0x5a, 0x11, 0x88 }; // data to transmit
    uint8_t rx[16];                              // receive buffer

    mwf::the_spi1->ssel_select(0);
    mwf::the_spi1->transfer_blocking(tx, rx, 4); // four bytes transfer
    CLOCK_uDelay(5); // wait 5us
    mwf::the_spi1->transfer_blocking(tx, rx, 4); // four bytes transfer
    mwf::the_spi1->ssel_deselect();
}

class mwf::periph::spi

struct config

The mwf::periph::spi::config structure is defined as follows:

struct config {
    // evaluated only in init()
    E_PIN_MAIN pin_conf;    // master pin configuration (so far not used)
    E_PIN_SSEL pin_ssel[3]; // SSEL0..2 (assignment settings for slave select pins.
                            // At least pin_ssel[0] shall be configured.

    // evaluated in conf(), reconf()
    uint32_t baud;      // SPI frequency (default 50Mhz)
    E_SPI_DIR dir;      // transfer LSB first
    E_SPI_MODE mode;	// SPI mode (clock polarity and detect edge)
    uint8_t bits;       // bit width (0:default=8, ...)
    uint8_t ssel;       // 0..3 or 0x80..0x80 (if MSB is set, assert/deassert SSEL automatically)
};

You set values in the structure and call init(). The structure’s settings are copied internally during the init() call, so you can discard the structure’s memory area afterward.

Here is an explanation of each member of the structure:

Signal NameDescription
pin_confSpecifies the pin assignment (primary or alternate). If E_PIN_CONF::NODEF (=0) is selected, the setting from global_init_spi1_manager() is used.
pin_ssel[3]Specifies the SELECT pins. Index 0 of the array specifies the pin for SPI SELECT 0 (SSEL0), index 1 for SSEL1, and index 2 for SSEL2. SSEL0 must always be specified, while SSEL1 and SSEL2 should be set to E_PIN_SSEL::SSEL_VOID=0. If you use two types of pins, specify SSEL0 and SSEL1; if you use three, store values in all of them.
*Note: If you specify a software-controlled pin (e.g., E_PIN_SSEL::SSEL0_PIO3), all select pins will be software-controlled. With software control, the pins are set to a continuous HIGH level output and change to a LOW level when selected. TWENETcmpt (AHI library compatible) uses software control.
*Note: With hardware control, the SELECT pin control follows the behavior of SPI_MasterTransferNonBlocking() in fsl_spi.c.
baudSpecifies the SPI clock frequency. It can be set up to 32MHz, but frequencies around 1MHz are often used for sensor devices.<br />(Behavior follows spi_master_config_t::bandRate_Bps in fsl_spi.h and SPI_MasterSetBaud() in fsl_spi.c)
modeSPISEL is specified in init().
bitsThis is the transfer unit. 8 is usually specified. It can be set from 1 to 16. If 9 bits or more are specified, the byte array for data transfer is read in 2-byte units, requiring twice the amount of data. The first byte represents 8 bits from the LSB, and the second byte represents the remaining bits.
(Behavior follows SPI_MasterTransferBlocking() in fsl_spi.h)
sselThis is the SPI SELECT. Specify 0 to 2.

enum class E_PIN_CONF

enum class E_PIN_CONF : uint8_t {
    NODEF = 0,   // Not specified
    PRIMARY = 1, // Primary assignment (PIO10/11)
    ALT = 2      // Alternate assignment (PIO15/16)
};
// Type for assignments, comparisons, etc. between enum class and int types.
using wE_PIN_CONF = mwf::enum_wapper<E_PIN_CONF>;

This is an enumeration for specifying pin assignments.

enum class E_PIN_SSEL

enum class E_PIN_SSEL : uint8_t {
    SSEL_VOID = 0, // Undefined
    SSEL_PRIMARY,  // Primary setting pin
    SSEL_ALT,      // Alternate setting pin
    SSEL_SOFT = 0x10,
    SSEL0_PIO3,  // SSEL0 is software-controlled, using PIO3
    SSEL1_PIO16, // SSEL1 is software-controlled, using PIO16
    SSEL2_PIO17, // SSEL2 is software-controlled, using PIO17
    SSEL1_PIO4,  // SSEL1 is software-controlled, using PIO4
    SSEL2_PIO13, // SSEL2 is software-controlled, using PIO13
};

This enumeration determines the arrangement of the SPI SELECT pins. The corresponding value is stored in spi::config::pin_ssel[3].

  • Set pin_ssel[] according to the number of devices used.

    • For one device, set pin_ssel[0]. pin_ssel[1] and pin_ssel[2] should be SSEL_VOID.
    • For two devices, set pin_ssel[0] and pin_ssel[1]. pin_ssel[2] should be SSEL_VOID.
    • For three devices, set pin_ssel[0], pin_ssel[1], and pin_ssel[2].
  • To specify hardware control, use SSEL_PRIMARY or SSEL_ALT (and SSEL_VOID). If you mix them, it will result in software control.

enum class E_SPI_DIR

enum class E_SPI_DIR {
    MSB_FIRST = 0,
    LSB_FIRST
};

This specifies the bit order. MSB_FIRST is typically used.

enum class E_SPI_MODE

enum class E_SPI_MODE {
    MODE_0_RISE = 0,
    MODE_1_FALL = 1,
    MODE_2_INV_FALL = 2,
    MODE_3_INV_RISE = 3,
};

This specifies the SPI transfer mode. It determines the clock’s detection edge and whether the H/L value at that time is 0 or 1. Set this according to the connected device’s datasheet.

global_init_spi1_manager(), global_deinit_spi1_manager()

static void global_init_spi1_manager(E_PIN_MAIN pin_conf = E_PIN_MAIN::PRIMARY);
static void global_deinit_spi1_manager();

These functions create and destroy the class object for using the SPI1 bus. During class object creation, you select the pin combination to use with pin_conf. You can specify E_PIN_MAIN::PRIMARY (value 0) or E_PIN_MAIN::ALT (value 1) for the pin configuration.

init()

void init();
void init(spi::config& cnf);
void init(spi::config&& cnf);

This function initializes the SPI bus. By providing the cnf parameter, you can set several configurations. If the parameter is omitted, it re-initializes with the previous settings.

  • Even if you are software-controlling the select pin in your user program, you must specify at least one. The specified pin will be configured as a GPIO output. By calling unset_ssel_auto(), the library will no longer control that pin.

reconf()

void reconf();

This function re-applies the peripheral parameters. To access the internal settings, use spi::config& get_conf(). Pin settings (pin_ssel[]) are not reflected by this procedure.

set_data_width()

void set_data_width(uint8_t bits);

This function changes the transfer data width. It is a lighter procedure than reconf().

set|unset|get_ssel_auto()

void set_ssel_auto();
void unset_ssel_auto();
bool get_ssel_auto();

Sets, unsets, and gets the automatic control flag for the select pin.

  • This is only effective when using software control.
  • When transfer_blocking() is called, the SELECT pin is automatically set to LOW. It is set back to HIGH upon completion.

ssel_select()

void ssel_select(uint8_t select);

This function specifies the select pin. select takes values of 0, 1, or 2, corresponding to SSEL0 through SSEL2.

  • With hardware or software control and the automatic control flag (set_ssel_auto()) enabled, pin control is performed when the transfer API is called.
  • With software control, regardless of the automatic control flag, the SELECT pin is set to LOW immediately after the ssel_select() call.
  • With hardware control, it calls reconf() to re-initialize. This process has a high time cost, so if you frequently switch between devices for transfers, please use software control.

ssel_deselect()

void ssel_deselect();

This function deselects the select pins.

  • With software control, all select pins are returned to a HIGH level.
  • With hardware control, it does nothing.
  • It does not change the pin specification from ssel_select().

Other

bool has_init(); // Returns true if init() has been executed
spi::config& get_conf(); // Accesses internally stored configuration information

Pin Assignments

For E_PIN_CONF::PRIMARY

SignalPIO NumberDescription
SCK0Clock signal
MOSI2SPIMOSI. TWELITE side is output, external SPI device side is input.
MISO5SPIMISO. TWELITE side is input, external SPI device side is output.

Select Pins

pin_sselE_PIN_SSELPIORemarks
SSEL0 pin_ssel[0]SSEL_PRIMARY3
SSEL_ALT16
SSEL0_PIO33Software-controlled
SSEL0_PIO1616Software-controlled
SSEL1 pin_ssel[1]SSEL_PRIMARY4
SSEL_ALT14
SSEL1_PIO44Software-controlled
SSEL1_PIO1414Software-controlled
SSEL1_PIO1616Software-controlled (Cannot specify SSEL0_PIO16)
SSEL_VOIDOnly use SSEL0 for selection
SSEL2 pin_ssel[2]SSEL_PRIMARY13
SSEL2_PIO1313Software-controlled
SSEL2_PIO1717Software-controlled
SSEL_VOIDOnly use SSEL0 and SSEL1 for selection
  • A maximum of three select pins can be set in order from SSEL0 to SSEL1 and SSEL2.
  • If any of the pin_ssel[] specifications are for software control, all select pins will be software-controlled by the library.

For E_PIN_CONF::ALT

SignalPIO NumberDescription
SCK15Clock signal
MOSI17SPIMOSI. TWELITE side is output, external SPI device side is input.
MISO18SPIMISO. TWELITE side is input, external SPI device side is output.

Select Pins

pin_sselE_PIN_SSELPIORemarks
SSEL0 pin_ssel[0]SSEL_PRIMARY16
SSEL_ALT3
SSEL0_PIO33Software-controlled
SSEL0_PIO1616Software-controlled
SSEL1 pin_ssel[1]SSEL_PRIMARY14SSEL0 must be specified
SSEL_ALT4
SSEL1_PIO44Software-controlled
SSEL1_PIO1414Software-controlled
SSEL_VOIDOnly use SSEL0 for selection
SSEL2 pin_ssel[2]SSEL_PRIMARY13
SSEL_ALT5Note that this is also the PRG pin.
SSEL2_PIO55Software-controlled. Note that this is also the PRG pin.
SSEL2_PIO1313Software-controlled
SSEL_VOIDOnly use SSEL0 and SSEL1 for selection
  • A maximum of three select pins can be set in order from SSEL0 to SSEL1 and SSEL2.
  • If any of the pin_ssel[] specifications are for software control, all select pins will be software-controlled by the library.

class mwf::periph::spi (sys_ev_handler)

on_sleep()

As a procedure before sleep, the SPI is returned to an unused state. If it has been initialized by init(), this state is saved.

on_wakeup()

If it was in an initialized state before sleep, it is re-initialized so that the SPI bus can be used.

2.10 - mwf_periph_wtimer - WTIMER, FRWT

mwf_periph_wtimer - WTIMER, FRWT
This is a peripheral object that summarizes the procedures for using the wake-up timer.

mwf_periph_wtimer - WWDT, FRWT

This implements the_wtimer, a peripheral object that summarizes the procedures for using the wake-up timer.

With TWENET, this is used implicitly, so no initialization is required in the user’s program.

The wake-up timer counts down based on the 32768Hz crystal oscillator built into the module. For example, if the timer starts from 32768, the counter will reach 0 and an interrupt will occur after 1 second. It is typically used for waking up from sleep. Since the counter continues to count down even after waking up, you can calculate the elapsed time since waking up by reading the counter value.

There are two wake-up timer channels: channel 0 uses a 40-bit counter (used as a 32-bit counter in this library), and channel 1 uses a 28-bit counter.

The FRWT (Free Running Wake Timer) procedure, which uses the wake-up timer, is also included. By taking advantage of its ability to operate with low current consumption during sleep, one of the two wake-up timer channels can be kept running constantly, allowing it to be used as a counter for real-time. In TWENET, FRWT functions with a specific setting, which allows for efficient waiting for ADC initialization, etc., while FRWT is running.

TWENET uses channel 0 as the FRWT and channel 1 as the regular wake-up timer.

Code example

  • include
#include "mwf_periph_wtimer.hpp"

class mwf::periph::wtimer

global_init_wtimer_manager(), global_deinit_wtimer_manager()

static void global_init_wtimer_manager();
static void global_deinit_wtimer_manager();

These functions create and destroy the the_wtimer class object.

init(), deinit()

void init();
void deinit();

These functions initialize or terminate the wake-up timer.

  • The u32ms parameter during initialization specifies the timeout in milliseconds (ms). If it is 0 or omitted, the timeout will be 4000ms.

start(), stop()

void start(uint8_t dev, uint32_t u32ct)
void stop(uint8_t dev)

These functions start or stop the wake-up timer.

  • For dev, specify the device number of the wake-up timer to be used (WTIMER0_DEVICE or WTIMER1_DEVICE).
  • For u32ct, specify the initial count value.
  • If you specify a wake-up timer channel that is currently running as an FRWT, the function will do nothing.

read()

uint32_t read(uint8_t dev)

This function reads the count value of the wake-up timer.

  • For dev, specify the device number of the wake-up timer to be used (WTIMER0_DEVICE or WTIMER1_DEVICE).
  • The value of a wake-up timer channel that is currently running as an FRWT cannot be read.

is_running()

bool is_running(uint8_t dev)

This function determines whether the wake-up timer is currently running.

  • For dev, specify the device number of the wake-up timer to be used (WTIMER0_DEVICE or WTIMER1_DEVICE).
  • If you specify a wake-up timer channel that is currently running as an FRWT, it returns false.

set_interrupt()

void set_interrupt(uint8_t dev, bool b_enabled)

This function specifies whether the wake-up timer should generate an interrupt.

  • For dev, specify the device number of the wake-up timer to be used (WTIMER0_DEVICE or WTIMER1_DEVICE).
  • Setting b_enabled to true enables interrupts. If this is not specified, an interrupt will not occur even when waking up from sleep. Note that once true has been specified for a wake-up timer, you cannot disable the interrupt by specifying false.
  • If you specify a wake-up timer channel that is currently running as an FRWT, the function will do nothing.

get_fired_status_on_wakeup()

uint8_t get_fired_status_on_wakeup()

This function is called after waking up from sleep. If the wake-up cause was a wake-up timer, the corresponding bit (WTIMER0_DEVICE_MASK or WTIMER1_DEVICE_MASK) will be set.

class mwf::periph::wtimer (sys_ev_handler)

on_sleep()

There are no special procedures.

on_wakeup()

This function confirms the wake-up cause, saves the information internally, and clears the interrupt status. The timer also does not stop.

freerun_start(), freerun_stop()

void freerun_start(uint8_t dev)
void freerun_stop()

These functions start and stop the FRWT. The count value is incremented at 32768Hz, starting from 0 at the beginning.

  • For dev, specify the device number of the wake-up timer (WTIMER0_DEVICE or WTIMER1_DEVICE).

freerun_is_running()

bool freerun_is_running()

Returns true if the FRWT is running.

freerun_is_device()

bool freerun_is_device(uint8_t dev)

Returns true if the specified device is the one running as an FRWT.

  • For dev, specify the device number of the wake-up timer (WTIMER0_DEVICE or WTIMER1_DEVICE).

freerun_ct_get()

uint32_t freerun_ct_get()

Returns the FRWT’s count value. The FRWT’s count value is not the wake-up timer’s value itself, but is converted to an incrementing value from 0 (roughly a value with its sign inverted).

Count Value Calculation Functions

These functions convert the FRWT count value to milliseconds or calculate the difference between two count values.

freerun_ct_convert_msec()

uint32_t freerun_ct_convert_msec(uint32_t ct, uint32_t* dec_part = nullptr)

This function converts the FRWT count value ct to milliseconds. If dec_part is specified, it sets the value of the 1/10th digit to a value from 0 to 9.

freerun_ct_diff()

int32_t freerun_ct_diff(uint32_t val_past, uint32_t val_now)

This function calculates the difference between two count values. It is essentially val_now - val_past, but it is calculated to account for cases where the counter returns to 0 after reaching its maximum value. Time differences up to half of the maximum counter value can be calculated, and if val_past is older, it returns a positive value.

freerun_ct_diff_msec()

int32_t freerun_ct_diff_msec(int32 vdiff)

This function converts the counter difference vdiff obtained from freerun_ct_diff() to milliseconds.

freerun_ct_diff_usec()

int32_t freerun_ct_diff_usec(int32 vdiff)
int32_t freerun_ct_diff_usec(uint32_t val_past, uint32_t val_now)

This function converts the counter difference vdiff obtained from freerun_ct_diff() or the counter difference calculated from val_past and val_now to microseconds.

  • Due to calculation, an int32_t overflow can occur (e.g., if the time difference exceeds approximately 2000 seconds).

2.11 - mwf_periph_wwdt - WWDT

mwf_periph_wwdt - WWDT
This is a peripheral object that summarizes the procedures for using the watchdog timer.

mwf_periph_wwdt - WWDT

the_wwdt, a peripheral object that summarizes the procedures for using the watchdog timer, is implemented.

With TWENET, this is used implicitly, so no initialization is required in the user’s program.

Code example

void setup_func() {
	mwf::gobal_init_wwdt_manager();
    the_wwdt.init(); // timeout in 4000ms approx.
}

// in some function called periodically (e.g. invoked by SysTick Timer.)
void do_every_tick() {
    the_wwdt.refresh();
}

class mwf::periph::wwdt

global_init_wwdt_manager(), global_deinit_wwdt_manager()

static void global_init_wwdt_manager();
static void global_deinit_wwdt_manager();

These functions create and destroy the the_wwdt class object.

init(), deinit()

void init(uint32_t u32ms = 0);
void deinit();

These functions initialize and stop the watchdog timer (*1).

  • The u32ms parameter during initialization specifies the timeout in milliseconds (ms). If it is 0 or omitted, the timeout will be 4000ms.
  • *1 Due to hardware limitations, a watchdog timer that has been started once cannot be stopped. deinit() is provided as a library procedure (e.g., when restarting the timer, you would execute deinit() and then call init() again).

set_timeout()

void set_timeout(uint32_t u32ms);

This function changes the watchdog timer’s timeout duration. For u32ms, specify the timeout duration in milliseconds (ms).

  • The validity of u32ms is not validated. While init() used 0 as a default value, the behavior of this function when 0 is provided is undefined.

refresh()

void refresh();

This is the refresh function that must be called before the watchdog timer’s timeout.

class mwf::periph::wwdt (sys_ev_handler)

on_sleep()

Performs the WWDT stop procedure.

on_wakeup()

Performs the WWDT start procedure.

  • If it was active before sleep, the WWDT is reactivated.

2.12 - class tick_counter - Stop Watch

class tick_counter - Stop Watch
Stop Watch is used to measure very short processing times in the msec and usec domains. It uses the microcontroller’s hardware counting function.

class tick_counter - Stop Watch

Used to measure very short processing times in the msec and usec ranges. It uses the microcontroller’s hardware counting function.

For this library code, it is recommended to keep its use experimental after sufficient verification. If measurement in units of approximately 30usec is sufficient, using the wake-up timer’s count value is simpler.

  • It controls the CoreDebug->DEMCR and DWT registers.

    • It is believed that these registers are not intended for general, widespread use. While you may not experience major issues during temporary time measurements in development, their use in firmware at the final operational stage is not recommended.
  • It is possible to construct multiple tick_counter objects simultaneously.

    • The counting function used is a single one and is shared among the objects.
    • The counting function is started when the first object is constructed and stopped when all objects are destroyed.

Example:

#include <mwf_stop_watch.hpp>

void some_func() {
    // ...

    // Start measurement 1
    mwf::periph::tick_counter sw;

    sw.lap(); // Start measurement 1 (although lap() is also called when sw is constructed, call it directly before the process for more precise measurement)
    // ...       // Process to be measured
    sw.lap(); // End measurement 1

    // Display value (Start measurement 1 to End measurement 1)
    PRINTF("%dusec", sw.get_us());

    // Next process
    sw.lap(); // Start measurement 2
    // ... // Process to be measured
    sw.lap(); // End measurement 2

    // Display value (Start measurement 2 to End measurement 2)
    PRINTF("%dusec", sw.get_us());
}

_start_counter(), _stop_counter()

static void _start_counter();
static void _stop_counter();

These functions start and stop the count timer using the CoreDebug feature.

tick_counter()

This is the constructor. If no other objects have been constructed, it starts the counter and also calls lap() to begin measurement.

~tick_counter()

This is the destructor. It stops the counter when all class objects have been destroyed.

lap()

This function saves the previous count value and stores the count value at the time it was called.

The elapsed time is obtained with get_us().

2.13 - mwf-utils - utils

mwf-utils - utils
Other utilities.

mwf_utils

Other utilities.

prepare_object()

    template <class T>
    static inline std::unique_ptr<T>& prepare_object(std::unique_ptr<T>& spobj, bool b_construct_if_null = true) {
        if (!spobj && b_construct_if_null) {
            spobj.reset(new T());
        }
        return spobj;
    }

This function references an object of the smart pointer std::unique_ptr<>. If the object has not been constructed, it is constructed using new T().

get_value_if()

// When getting a value from a function and proceeding with a process using that value
int v = some_func();
if (v != -1) {
    // Do something with the value of v
    printf("%d", v);
}

// Rewrite as follows
if (auto x = get_value_if::ne(some_func(), -1)) {
    printf("%d", x.value());
}

As shown in the example above, this is a utility class for writing code that uses a function’s return value under a certain condition, by using a variable declaration within an if statement.

In the example above, get_value_if::ne() is used. The first parameter is a function call that returns a value, and the second parameter specifies the value for comparison. In this case, the if block is evaluated only when the return value of some_func() is not -1. The types of the first and second parameters must be the same.

The following comparison expressions can be used: eq, ne, lt, le, gt, ge.

get_value_if::xx() (T is a type)Condition
eq(T lhs, const T rhs)(lhs == rhs)Returns true if the values are the same.
ne (T lhs, const T rhs)(lhs != rhs)Returns true if the values are different.
lt (T lhs, const T rhs)(lhs < rhs)Compares values, returns true if the value is smaller.
le (T lhs, const T rhs)(lhs <= rhs)Compares values, returns true if the value is less than or equal to.
gt (T lhs, const T rhs)(lhs > rhs)Compares values, returns true if the value is larger.
ge (T lhs, const T rhs)(lhs >= rhs)Compares values, returns true if the value is greater than or equal to.

Note: T indicates a type (a type parameter in a template construct).

3 - TWENETutils - TWENET Utility

A library that encapsulates general algorithms and peripheral procedures.
This library includes general algorithms and peripheral procedures.

TWENETutils - TWENET Utility

This library includes general algorithms and peripheral procedures. It corresponds to libTWENETutils.a.

3.1 - utils.h

Start Functions: main(), WarmMain()
Macros and functions available by including utils.h.

utils.h

This section introduces the macros and functions available by including utils.h.

S_OCTET(x)

Writes one byte to memory.

uint8 *q = &sTx.au8Data[0];

S_OCTET(0x12);
S_BE_WORD(0x1234);
S_BE_DWORD(0x12345678);

Declare uint8 *q as a local variable and use it as a pointer to the memory area where you want to write data. q++ is executed after the assignment operator is evaluated.

S_BE_WORD(x)

Writes two bytes to memory.

uint8 *q = &sTx.au8Data[0];

S_OCTET(0x12); 
S_BE_WORD(0x1234);
S_BE_DWORD(0x12345678);

Declare uint8 *q as a local variable and use it as a pointer to the memory area where you want to write data. q+=2 is executed after the assignment operator is evaluated.

BE stands for Big Endian, and LE for Little Endian.

S_BE_DWORD(x)

Writes four bytes to memory.

uint8 *q = &sTx.au8Data[0];

S_OCTET(0x12); 
S_BE_WORD(0x1234);
S_BE_DWORD(0x12345678);

Declare uint8 *q as a local variable and use it as a pointer to the memory area where you want to write data. q+=4 is executed after the assignment operator is evaluated.

BE stands for Big Endian, and LE for Little Endian.

G_OCTET()

Reads one byte from memory and stores the value in a uint8 type variable.

uint8 *p = &sRx.au8Data[0];

uint8 u8data1 = OCTET(); 
uint16 u16data2 = G_BE_WORD();
uint32 u32data3 = G_BE_DWORD();

Declare uint8 *p as a local variable and use it as a pointer to the memory area you want to read data from. p++ is executed after the = operator is evaluated.

G_BE_WORD()

Reads two bytes from memory and stores the value in a uint16 type variable.

uint8 *p = &sRx.au8Data[0];

uint8 u8data1 = OCTET(); 
uint16 u16data2 = G_BE_WORD();
uint32 u32data3 = G_BE_DWORD();

Declare uint8 *p as a local variable and use it as a pointer to the memory area you want to read data from. p+=2 is executed after the = operator is evaluated.

BE stands for Big Endian, and LE for Little Endian.

G_BE_DWORD()

Reads four bytes from memory and stores the value in a uint32 type variable.

uint8 *p = &sRx.au8Data[0];

uint8 u8data1 = OCTET(); 
uint16 u16data2 = G_BE_WORD();
uint32 u32data3 = G_BE_DWORD();

Declare uint8 *p as a local variable and use it as a pointer to the memory area you want to read data from. p+=4 is executed after the = operator is evaluated.

BE stands for Big Endian, and LE for Little Endian.

ENCODE_VOLT(x)

This function converts a value from 2000 to 3600 into an 8-bit value.

  • 1.95V to 2.80V is in 5mV increments.
  • 2.81V to 3.65V is in 10mV increments.
// utils.h definition
#define ENCODE_VOLT(m) \
	(m < 1950 ? 0 : \
		(m > 3650 ? 255 : \
			(m <= 2802 ? ((m-1950+2)/5) : ((m-2800-5)/10+171)) ))
...
uint16 u16Volt = 2860;
uint8 u8Volt_enc = ENCODE_VOLT(u16Volt);
uint16 u16Volt_dec = DECODE_VOLT(u8Volt_Enc);

Values from 2000 to 2800 are assigned to an 8-bit value in increments of 5, and values from 2800 onwards are assigned in increments of 10.

DECODE_VOLT(x)

This function converts the 8-bit value obtained from ENCODE_VOLT() back to its original value.

  • 1.95V to 2.80V is in 5mV increments.
  • 2.81V to 3.65V is in 10mV increments.
// utils.h definition
#define DECODE_VOLT(i) \
	(i <= 170 ? (1950+i*5) : (2800+(i-170)*10) )
...
uint16 u16Volt = 2860;
uint8 u8Volt_enc = ENCODE_VOLT(u16Volt);
uint16 u16Volt_dec = DECODE_VOLT(u8Volt_Enc);

Values from 2000 to 2800 are assigned to an 8-bit value in increments of 5, and values from 2800 onwards are assigned in increments of 10.

vPortAsInput(c)

Sets port c as input.

#define vPortAsInput(c) vAHI_DioSetDirection(1UL << (c), 0)

vPortAsOutput(c)

Sets port c as output.

#define vPortAsOutput(c) vAHI_DioSetDirection(0, 1UL << (c))

vPortSetHi(c)

Sets port c to a high state.

#define vPortSetHi(c) vAHI_DioSetOutput(1UL << (c), 0)

vPortSetLo(c)

Sets port c to a low state.

#define vPortSetLo(c) vAHI_DioSetOutput(0, 1UL << (c))

vPortSet_TrueAsLo(c, s)

Sets port c to Lo if s is TRUE, and to Hi if s is FALSE.

#define vPortSet_TrueAsLo(c, s)  vAHI_DioSetOutput((s) ? \
    0 : 1UL << (c), s ? 1UL << (c) : 0)

bPortRead(c)

Reads port c. Returns TRUE if the level is low.

#define bPortRead(c) ((u32AHI_DioReadInput() & \
    (1UL<<(c))) ? FALSE : TRUE)

u32PortReadBitmap()

Reads port c. Returns TRUE if the level is low.

#define u32PortReadBitmap() (u32AHI_DioReadInput())

A value of 1 in the bitmap represents Hi, and 0 represents Lo.

bPortCheckBitmap(bitmap, c)

This function returns TRUE if the bit corresponding to port c in the read bitmap is at a low level.

#define bPortCheckBitmap(bitmap, c) \
    (bitmap & (1UL<<(c))) ? FALSE : TRUE)

vPortDisablePullup(c)

This function disables the pull-up for port c.

#define vPortDisablePullup(c) vAHI_DioSetPullup(0x0, 1UL << (c))

_C

This macro is used to define a scope within a switch statement. It is written as _C { … }.

#define _C if(1)
// for example

switch(c) {
case 1:
  _C {
    uint8 u8work;
    ; // work
  } break;
default:
}

LB

This is a newline string literal (CRLF).

Since it is a two-byte string literal, it cannot be used with vPutChar().

#define LB "\r\n"

vWait() function

This function waits for a specified amount of time using a loop.

void vWait(uint32 c) {
	static volatile uint32 u32ct = 0;
	while (c-- > 0)
		u32ct++;
}

The process is as described in the source code.

vAnalogueConfig(), vAnalogueDisable()

These functions bundle the procedures for initializing and stopping the ADC function. They are intended for compatibility with existing code.

void vAnalogueConfig(void) {
#if defined(JN516x)
	if (!bAHI_APRegulatorEnabled()) {
		vAHI_ApConfigure(E_AHI_AP_REGULATOR_ENABLE,
				E_AHI_AP_INT_DISABLE,
				E_AHI_AP_SAMPLE_4,
				E_AHI_AP_CLOCKDIV_1MHZ,
				E_AHI_AP_INTREF);

		while (!bAHI_APRegulatorEnabled())
			;
	}
#elif defined(CPU_JN518X)
#endif

void vAnalogueDisable(void) {
#if defined(JN516x)
	vAHI_ApConfigure(E_AHI_AP_REGULATOR_DISABLE,
			E_AHI_AP_INT_DISABLE,
			E_AHI_AP_SAMPLE_4,
			E_AHI_AP_CLOCKDIV_1MHZ,
			E_AHI_AP_INTREF);
#elif defined(CPU_JN518X)
#endif
}

Other Macro Definitions

// 64bit mac address
#define MAC_EXT_ADDR_TO_64BIT(ext) ((uint64)(ext.u32L) | (((uint64)(ext.u32H)) << 32))

// TIME COMPARE
#define u32TimeDiff(ref, now) (now - ref < 0x7FFFFFFF ? now - ref : )

// IO settings
#define vPortSetHi(c) vAHI_DioSetOutput(1UL << (c), 0)
#define vPortSetLo(c) vAHI_DioSetOutput(0, 1UL << (c))
#define vPortSet_TrueAsLo(c, s)  vAHI_DioSetOutput((s) ? 0 : 1UL << (c), s ? 1UL << (c) : 0)
#define vPortAsInput(c) vAHI_DioSetDirection(1UL << (c), 0)
#define vPortAsOutput(c) vAHI_DioSetDirection(0, 1UL << (c))
#define bPortRead(c) ((u32AHI_DioReadInput() & (1UL<<(c))) ? FALSE : TRUE) // Lo as True
#define u32PortReadBitmap() (u32AHI_DioReadInput())
#define bPortCheckBitmap(bitmap, c) ((bitmap & (1UL<<(c))) ? FALSE : TRUE)
#define vPortDisablePullup(c) vAHI_DioSetPullup(0x0, 1UL << (c))

#if defined(JN516x) || defined(CPU_JN518X)
#define PORT_KIT_SW1 2
#define PORT_KIT_SW2 3
#define PORT_KIT_SW3 10
#define PORT_KIT_SW4 9
#define PORT_KIT_LED1 17
#define PORT_KIT_LED2 13
#define PORT_KIT_LED3 12
#define PORT_KIT_LED4 11
#endif

#define PORT_KIT_SW1_MASK (1UL << PORT_KIT_SW1)
#define PORT_KIT_SW2_MASK (1UL << PORT_KIT_SW2)
#define PORT_KIT_SW3_MASK (1UL << PORT_KIT_SW3)
#define PORT_KIT_SW4_MASK (1UL << PORT_KIT_SW4)
#define PORT_KIT_SW_ALL2_MASK (PORT_KIT_SW1_MASK | PORT_KIT_SW2_MASK)
#define PORT_KIT_SW_ALL4_MASK (PORT_KIT_SW1_MASK | PORT_KIT_SW2_MASK | PORT_KIT_SW3_MASK | PORT_KIT_SW4_MASK)

#define PORT_KIT_LED1_MASK (1UL << PORT_KIT_LED1)
#define PORT_KIT_LED2_MASK (1UL << PORT_KIT_LED2)
#define PORT_KIT_LED3_MASK (1UL << PORT_KIT_LED3)
#define PORT_KIT_LED4_MASK (1UL << PORT_KIT_LED4)
#define PORT_KIT_LED_ALL2_MASK (PORT_KIT_LED1_MASK | PORT_KIT_LED2_MASK)
#define PORT_KIT_LED_ALL4_MASK (PORT_KIT_LED1_MASK | PORT_KIT_LED2_MASK | PORT_KIT_LED3_MASK | PORT_KIT_LED4_MASK)

// UART related
#define WAIT_UART_OUTPUT(P) SERIAL_vFlush(P)

// IO clock (on JN514x, IO runs at 16Mhz regardless of CPU clock.
#if defined(JN516x)
#define u32IO_FREQ_HZ 16000000UL
#elif defined(CPU_JN518X)
//#define u32IO_FREQ_HZ 32000000UL
#define u32IO_FREQ_HZ 16000000UL
#endif

void vAnalogueConfig(void);
void vAnalogueDisable(void);

void vWait(uint32 c);

3.2 - Timer Library

Timer library
Introducing the Timer library.

Timer Library

tsTimerContext

A structure for configuration used by the Timer library.

  • Clear it to 0.
  • Ensure it is statically allocated.
TypeNameExplanation
uint8u8DeviceSpecifies the timer device (E_AHI_DEVICE_TIMER0..4).
uint16u16HzSpecifies the timer frequency in Hz.
uint8u8PreScaleSets the prescaler for the 16MHz clock.
bool_tbPWMOutIf TRUE, performs PWM output.
bool_tbDisableIntIf TRUE, disables interrupts.

vTimerConfig()

Explanation

Initializes the Timer.

Arguments

TypeNameDescription
tsTimerContextpsTCThe timer configuration structure.

Return Value

None.

Sample

tsTimerContext sTimerApp; // global or static allocation

// set 64ticks/sec
memset(&sTimerApp, 0, sizeof(tsTimerContext));
sTimerApp.u8Device = E_AHI_DEVICE_TIMER0;
sTimerApp.u16Hz = 64;
sTimerApp.u8PreScale = 4; // 15625ct@2^4

vTimerStart()

Explanation

Starts the Timer.

This function can also be called for a Timer that has already been started. It is used when changing the duty cycle, etc.

Arguments

TypeNameDescription
tsTimerContextpsTCThe timer configuration structure.

Return Value

None.

Sample

// initialize and start
vTimerConfig(&sTimerApp); // initialize
vTimerStart(&sTimerApp); // start

// change duty
sTimerPWM.u16Duty = 256; // set new duty ratio
vTimerStart(&sTimerPWM); // just start again to change duty

vTimerStop()

Explanation

Stops the operation of the Timer.

Arguments

TypeNameDescription
tsTimerContextpsTCThe timer configuration structure.
Return Value

None.

Sample

// just stop the timer
vTimerStop(&sTimerApp);
...
// restart
vTimerStart(&sTimerApp);
...
// now, disable timer completely
vTimerStop(&sTimerApp);
vTimerDisable(&sTimerApp);

vTimerDisable()

This function destroys the Timer.

Arguments

TypeNameDescription
tsTimerContextpsTCThe timer configuration structure.

Return Value

None.

Sample

// just stop the timer
vTimerStop(&sTimerApp);
...
// restart
vTimerStart(&sTimerApp);
...
// now, disable timer completely
vTimerStop(&sTimerApp);
vTimerDisable(&sTimerApp);

3.3 - fprintf Library

fprintf library
This is a simple implementation of fprintf.

fprintf Library

This is a simple implementation of fprintf.

{{< hint color=“info” >}} This library is provided for source code compatibility. For new implementations, it is recommended to use TWENETmcu/printf. {{< /hint >}}

Reference

tsFILE

A structure that defines the output destination specified by vfPrintf() and vPutChar().

Members
TypeNameDescription
uint8u8DeviceSpecifies the serial port (E_AHI_UART_0 or E_AHI_UART_1).
bool_t (*) (uint8 u8Device, uint8 u8Char)bPutCharA function pointer for output. For the SERIAL library, SERIAL_bTxChar() is prepared, so specify that.

{% hint style=“info” %} SERIAL_bTxChar() puts the byte passed as u8Char into the FIFO queue within the SERIAL library.

By preparing your own output function, you can use this for outputting strings to destinations other than UART. {% endhint %}

Sample code
#include "serial.h"
#include "fprintf.h"

tsFILE sSerStream;
tsSerialPortSetup sSerPort;

void vSerialInit(uint32 u32Baud, tsUartOpt *pUartOpt) {
	// initialize sSerPort
	...
	SERIAL_vInit(&sSerPort);

	// for vfPrintf()
	sSerStream.bPutChar = SERIAL_bTxChar;
	sSerStream.u8Device = E_AHI_UART_0;
}

void vSerOut() {
    vfPrintf(&sSerStream, "HELLO!");
}

Here is an example of the character LCD output code.

#include "serial.h"
#include "fprintf.h"

tsFILE sLcdStream;

// handle LCD display
PUBLIC bool_t LCD_bTxChar(uint8 u8Device, uint8 u8Data) {
	int i;

	switch (u8Data) {
	case '\n':
	...
}

void vInitHardware() {
    /* Initialise the LCD */
    vLcdReset(3, 0);

    /* register for vfPrintf() */
    sLcdStream.bPutChar = LCD_bTxChar;
    sLcdStream.u8Device = 0xFF;
}

void vSomeOutput() {
    vfPrintf(&sLcdStream, "Hello World!\n");
}

vfPrintf()

Explanation

This function outputs to the destination specified by the tsFILE structure (UART) using printf format.

Arguments

TypeNameDescription
tsFILE*psStreamOutput destination
const char *pcFormatOutput format
Variable arguments
Supported Formats
sString
dInteger (up to 32 bits)
uUnsigned integer (up to 32 bits)
xHexadecimal. a-f are lowercase.
XHexadecimal. A-F are uppercase.
bBit sequence

Return Value

None.

Sample

void cbToCoNet_vMain(void) {
	while (!SERIAL_bRxQueueEmpty(sSerPort.u8SerialPort)) {
		int16 i16Char;
		i16Char = SERIAL_i16RxChar(sSerPort.u8SerialPort);
		vfPrintf(&sSerStream, "\n\r## [%c] --> ", i16Char);
	    SERIAL_vFlush(sSerStream.u8Device);
		...
	}
}

vPutChar()

Explanation

This function outputs one byte to the destination specified by the tsFILE structure (UART).

Arguments

TypeNameDescription
tsFILE*psStreamOutput destination
uint8u8CharOutput byte

Return Value

None

Sample

#define IS_ASC(c) ((c) >= 0x20 && (c) <= 0x7e)

void cbToCoNet_vRxEvent(tsRxDataApp *pRx) {
	uint8 u8i;
	vfPrintf(&sSerStream, LB"RX(len=%d):[", pRx->u8Len);
	for (i = 0; i < pRx->u8Len; i++) {
		uint8 c = pRx->auData[i];
		vPutChar(&sSerStream, IS_ASC(c) ? c : '.');
	}
}

4 - TWENETcmpt - AHI Compatibility Layer

Compatibility layer for the GOLD series providing APIs compatible with the BLUE / RED series
Explanation of the TWENETcmpt library. It enables the use of some AHI functions, previously available on TWELITE BLUE/RED, on TWELITE GOLD.

TWENETcmpt - AHI Compatibility Layer

This library is intended to provide compatibility with the AHI library.

  • It aims to enable the build and operation of TweApps, not to achieve full compatibility.
  • The implementation uses the TWENETmwf library (a C++ library implemented with the FSL library).

Below are notes regarding various definitions of the compatibility layer.

LinkDescription
Common & OthersMiscellaneous functions
ADCADC-related APIs
GPIOGPIO-related APIs
PWMPWM-related APIs
I2C (SMBus)I2C-related APIs
SPISPI bus
RandomRandom number generation
UARTUART-related APIs
WDTWatchdog Timer
WTIMERWake Timer, FRWT
OnChipTempOn-chip temperature sensor (ADC)

4.1 - AHI-Compatible Functions

Explanation of the TWENET library and the AHI compatibility layer
This section covers general topics for AHI-compatible functions and provides explanations for AHI functions not associated with any specific peripheral.

AHI-Compatible Functions

Some of the AHI functions are implemented for source-level compatibility.

The following describes the AHI-compatible functions. Some items such as SPI and I2C are documented in separate files.

General Functions

u32AHI_Init()

uint32 u32AHI_Init();

Performs initialization for the AHI library in principle, but in this library, only a subset of variables is initialized.

bAHI_SetClockRate(), u8AHI_GetSystemClkRate()

bool_t bAHI_SetClockRate(uint8 u8clk_code);
uint8 u8AHI_GetSystemClkRate();

Sets or retrieves the CPU clock speed.

The configured clock values differ significantly from those of TWELITE BLUE/RED, so caution is required.

u8clk_codeTWELITE BLUE/REDTWELITE GOLD
04Mhz12Mhz
18Mhz12Mhz
216Mhz32Mhz
332Mhz48Mhz
4..ConfigurableIgnored
  • Although clocks such as kFROM1M_to_MAIN_CLK can be configured in the fsl library, they are disabled here due to severe operational issues.
  • Using a debugger may interfere with clock changes.
  • The default value is 2, corresponding to 32Mhz (TWELITE GOLD). (Reference: 16MHz on TWELITE BLUE/RED)

bAHI_Set32KhzClockMode()

bool_t bAHI_Set32KhzClockMode(uint8 u8mode);

Does nothing.

vAHI_CpuDoze()

static inline void vAHI_CpuDoze() { __WFI(); }

Enters the low-power DOZE state while waiting for interrupts. On TWELITE-GOLD, it issues WFI (Wait For Interrupt).

vAHI_SwReset()

static inline void vAHI_SwReset() { NVIC_SystemReset(); }

Performs a reset.

u16AHI_PowerStatus()

uint16 u16AHI_PowerStatus();

This function reports the following bitmaps:

BitDescription
bit01 when waking up from sleep
bit11 when RAM was retained

At POR, the value is 0, and for normal wake-up from RAM-retention sleep, the value is 3.

vAHI_BrownOutConfigure()

static inline void vAHI_BrownOutConfigure(
    uint8       const u8VboSelect,
    bool_t      const bVboRstEn,
    bool_t      const bVboEn,
    bool_t      const bVboIntEnFalling,
    bool_t      const bVboIntEnRising) { ; } // DUMMY FUNC

This definition exists only to avoid compilation errors. The function itself does nothing.

About Sleep

void ToCoNet_vSleep(uint8 u8Device, uint32 u32Periodms, bool_t bPeriodic, bool_t bRamOff)

Sleep in the TWENET C library uses the ToCoNet_vSleep() function.

Note: In the mwx library, use the_twelite.sleep().

  • If bRamOff is set to TRUE, the system enters sleep mode without retaining any RAM segments. Even in this case, PM_POWER_DOWN from the JN518x FSL library definitions is used, not PM_DEEP_DOWN.

About Sleep Failures (TWELITE GOLD)

On TWELITE GOLD, the procedure for sleep transition (POWER_EnterPowerMode()) in the semiconductor library occasionally fails, resulting in the device not entering sleep mode. To address this, the following measures are taken:

  • When the semiconductor library procedure fails, the function exits immediately, but after a delay loop equivalent to 100 µsec (DelayLoopN(100)), the sleep procedure is retried.
  • If the above retry fails 3 times, ToCoNet_vSleep() enters an infinite loop, and a watchdog timer reset normally occurs. In our experience, 2 or 3 retries have not been observed, but we allow up to 3 retries as a precaution.
  • After executing the above sleep procedure, if the value of extern uint8 g_twenet_power_down_fails; is non-zero upon waking up from sleep, it indicates that retries were performed. However, this variable is reset when a watchdog timer reset occurs.

For internal processing

u32AppApiInit()

uint32
u32AppApiInit(PR_GET_BUFFER prMlmeGetBuffer,
              PR_POST_CALLBACK prMlmeCallback,
              void *pvMlmeParam,
              PR_GET_BUFFER prMcpsGetBuffer,
              PR_POST_CALLBACK prMcpsCallback,
              void *pvMcpsParam);

Performs the initialization process for AppQAPI.

vAHI_RegEvMgr_MW()

void vAHI_RegEvMgr_MW();

Constructs the management object (mwf::the_sys_ev_manager) for managing class objects in the TWENETmwf library.

vAHI_OnWakeup_MW(), vAHI_OnWakeupRamOff_MW()

void vAHI_OnWakeup_MW(bool_t b_init_2nd);
void vAHI_OnWakeupRamOff_MW(bool_t b_init_2nd);

This procedure is executed upon wake-up. Refer to the processing in twenet_main.c of TWENETmcu.

  • Executes the wake-up processing of class objects in the TWENETmwf library: mwf::the_sys_ev_manager->on_wakeup().
  • Calls vAHI_DioOnWakeup_MW() to store the pins that triggered the wake-up.
  • If b_init_2nd is FALSE, it is called in the early stage of startup; if TRUE, it is called after a certain amount of initialization has been completed (before cbAppWarmStart(TRUE) is called).

vAHI_OnWakeupRamOff_MW() is called when waking up from RAM non-retentive sleep.

  • If b_init_2nd is FALSE, it is called in the early stage of startup; if TRUE, it is called after a certain amount of initialization has been completed (after cbAppWarmStart(TRUE) is called).

vAHI_OnSleep_MW()

vAHI_OnSleep_MW();

This procedure is executed before entering sleep.

  • Executes the pre-sleep processing of class objects in the TWENETmwf library: mwf::the_sys_ev_manager->on_sleep().
  • Calls vAHI_DioOnSleep_MW() to configure the DIO wake-up pins.

vAHI_DMAEnable_MW(), vAHI_DMADisable_MW()

void vAHI_DMAEnable_MW();
void vAHI_DMADisable_MW();

Enables or disables the DMA feature.

vAHI_DMADisable_MW() does not perform any operation.

4.2 - ADC-Related AHI Functions and Explanations

TWENET Library, AHI Functions and Explanations Related to ADCs
Explanation of the AHI functions related to ADC in the TWENET library.

ADC

Some parts related to AHI’s ADC (Analog-to-Digital Conversion) are implemented for the purpose of source code compatibility.

Overview

The hardware specifications of the ADC vary depending on the model.

TWELITE BLUETWELITE REDTWELITE GOLD
Resolution (bits)10bit10bit12bit
Full Scale2470mV2470mV3600mV
Number of Channels
(not supported by API)
44 (2)4 (2)

This library provides processing for using four channels (ADC0..3) and Vcc.
However, compatibility of conversion time or conversion data is not handled by the library; it is assumed that adjustments will be made in the application source.

For conversions up to 6 pins or for ADC combining multiple channels, the AHI library does not provide support; please use mwf::the_adc directly.

Related: On-chip Temperature Sensor

Pins

PIONotes
ADC015
ADC114Shared with DIO8
ADC216
ADC317

AHIcmpt_ADC.cpp

This library describes the differences from the AHI library for TWELITE BLUE/RED.
For API specifications, please also refer to the AHI library manual.

vAHI_ApConfigure()

void   vAHI_ApConfigure(
    bool_t      bAPRegulator,
    bool_t      bIntEnable,
    uint8       u8SampleSelect,
    uint8       u8ClockDivRatio,
    bool_t      bRefSelect);

Initializes the ADC (mwf::the_adc object construction and the_adc->init() initialization).

  • Specify bAPRegulator as TRUE to enable the ADC. If set to FALSE, the ADC is disabled.
  • Specify bIntEnable as TRUE to enable ADC interrupts.
  • u8SampleSelect and bRefSelect are ignored.
  • u8ClockDivRatio is also currently not applied.
  • A stabilization wait process for the analog circuit using bAHI_APRegulatorEnabled() is required.

bAHI_APRegulatorEnabled()

bool_t bAHI_APRegulatorEnabled(void)

When the wake timer (FRWT) is not running (which is the default in the C library), this function performs a fixed delay process (300 µsec). In this case, it is recommended to call this function immediately after invoking vAHI_ApConfigure(). Even if sufficient time has already passed, the fixed delay will still be executed.

When FRWT is enabled, the function performs the required waiting process based on the timer count value. If sufficient time has already passed, no additional waiting will be performed within this function.

vAHI_APRegisterCallback()

void   vAHI_APRegisterCallback(PR_HWINT_APPCALLBACK prApCallback);

Registers an interrupt handler. This will be called when the ADC conversion is completed.

vAHI_AdcEnable()

void   void   vAHI_AdcEnable(
    bool_t      bContinuous,
    bool_t      bInputRange,
    uint8       u8Source);

Configures the ADC conversion.

  • If bContinuous is selected, continuous conversion is performed. However, since internal interrupts occur on each conversion, performance considerations are necessary.
  • Specifying bInputRange has no effect because the hardware does not support this feature.
  • During this call, the pin corresponding to u8Source is configured for ADC use.
  • If bAHI_APRegulatorEnabled() was not executed after vAHI_ApConfigure() and the waiting process was skipped, the waiting process will be performed within this call.

vAHI_AdcDisable()

void   vAHI_AdcDisable(void);

Stops the ADC.

vAHI_AdcStartSample()

 void   vAHI_AdcStartSample(void);

Starts the ADC conversion.

  • In principle, the initial state is set as input; however, strictly speaking, the initial state is determined by the BOARD_InitPins() initialization in the TWENETmcu library’s pinmux.c.

bAHI_AdcPoll()

bool_t bAHI_AdcPoll(void);

Used for the polling wait process while(bAHI_AdcPoll()); to wait for ADC completion.

  • After the ADC completion interrupt, this call returns FALSE only once.

u16AHI_AdcRead(), i16AHI_AdcRead_mv()

uint16 u16AHI_AdcRead(void);
int16 i16AHI_AdcRead_mv(void); // 非AHI独自関数

Reads the executed ADC value.

  • u16AHI_AdcRead() returns the ADC value in 12-bit (0..4095). On error, it returns 0xffff.
  • i16AHI_AdcRead_mv() is a custom function not present in the AHI library. It returns the ADC value in mV, and on error, it returns -32768.

s_adc_int_handler()

static void s_adc_int_handler(uint32_t a1, uint32_t a2);

A static function defined in AHIcmpt_ADC.cpp that acts as an interrupt handler when the ADC conversion completes, passing the interrupt to TWENET’s AppQApi.

  • If a callback function is specified with vAHI_APRegisterCallback(), this handler will not be called.

Experimental Implementation

Batch Processing for Multiple Channels

// TWELITE GOLD only
//   Uses the FSL driver feature to acquire ADC values from multiple channels in a single operation.

// Execute ADC (parameters are the same as vAHI_AdcEnable())
void   vAHI_AdcEnableSeq(
    bool_t      bContinuous,
    bool_t      bInputRange,
    uint32      u32MaskSource);
// Read ADC value
uint16 u16AHI_AdcReadSeq(
    uint8     u8Source
    );
// Read ADC value (in mV)
int16 i16AHI_AdcReadSeq_mv(
    uint8     u8Source
    );

sensor_driver, adc.c, adc.h

sensor_driver is a set of processing functions used in existing TWEApps applications, providing a mechanism to abstract sensor processing. adc.c and .h describe the sequential processing for operating the on-chip ADC with sensor_driver, including issuing a series of commands, waiting, and acquiring data. Additionally, TWENETmwx/sensors/legacy contains implementations for several sensors other than ADC.

When migrating projects from TWELITE BLUE/RED to TWELITE GOLD, use the adjusted files stored in App_Twelite/Common. However, since project contents may differ, modifications may be required as needed.

Source NameDescription
adc.cADC processing part (ADC value conversion adjusted for TWELITE GOLD’s range)
adc.hDefinition part
sensor_driver.cSensor processing abstraction part
sensor_driver.hDefinition part

Code Example

Please refer to the comments within the following code.

#include "sensor_driver.h"
#include "adc.h"

tsObjData_ADC sObjADC; // ADC management structure (data section)
tsSnsObj sADC;         // ADC management structure (control section)
int16 a1,a2,ab;        // Variables for storing results

...
    // ADC initialization
    vSnsObj_Init(&sADC);
    vADC_Init(&sObjADC, &sADC, TRUE);
    vADC_WaitInit(); // Wait for hardware initialization

...
    // Specify the ports to measure with ADC (here: power supply voltage, ADC1, ADC2)
    sObjADC.u8SourceMask = TEH_ADC_SRC_VOLT
        | TEH_ADC_SRC_ADC_1 | TEH_ADC_SRC_ADC_2;

    // Start ADC
    vSnsObj_Process(&sADC, E_ORDER_KICK); // Start command

// Wait until processing of one ADC channel completes (=E_AHI_DEVICE_ANALOGUE interrupt)
// and call vSnsObj_Process() sequentially.
void cbToCoNet_vHwEvent(uint32 u32DeviceId, uint32 u32ItemBitmap) {
    switch (u32DeviceId) {
    case E_AHI_DEVICE_ANALOGUE:
        // ADC completion interrupt
        vSnsObj_Process(&sADC, E_ORDER_KICK);
        if (bSnsObj_isComplete(&sADC)) {
            // All channels have finished processing.
            // The values are stored as follows:
            a1=sObjADC.ai16Result[TEH_ADC_IDX_ADC_1]; // ADC1 [mV]
            a2=sObjADC.ai16Result[TEH_ADC_IDX_ADC_2]; // ADC2 [mV]
            ab=sObjADC.ai16Result[TEH_ADC_IDX_VOLT];  // Power supply voltage [mV]

            // Return to the initial state before ADC start
            vSnsObj_Process(&sADC, E_ORDER_KICK);

            // For continuous execution, call E_ORDER_KICK again
            vSnsObj_Process(&sADC, E_ORDER_KICK);
        }
        break;

    default:
        break;
    }
}

Functions

vSnsObj_Init()

void vSnsObj_Init(tsSnsObj *pSnsObj)

Initializes the sensor management structure. Call this function right before vADC_Init().

vADC_Init()

void vADC_Init(tsObjData_ADC *pData, tsSnsObj *pSnsObj, bool_t bInitAPR)

Initializes the ADC. Prepare the tsObjData structure (for storing results) and the tsSnsObj structure (for ADC management) in advance.

  • If bInitAPR is TRUE, the ADC hardware is initialized. Since hardware initialization takes some time, always execute vADC_WaitInit() to wait for initialization.

vSnsObj_Process()

void vSnsObj_Process(tsSnsObj *pObj, teEvent eEv)

Advances the ADC processing. Specifically, this function is called each time the conversion for one ADC port is completed.

During this process, the ADC value is retrieved, converted to mV, and stored in the tsSnsObj structure.

This process handles events for the state transitions managed by the tsSnsObj structure. Immediately after calling this process, call bSnsObj_isComplete() to check whether processing is complete. To return to the initial state, execute this process again with E_ORDER_KICK as the argument (in other words, to run the ADC again, execute E_ORDER_KICK twice after completion).

tsObjData_ADC structure

This structure contains the specified ADC channels and the resulting voltage values.

  • u8SourceMask: A bitmap specifying the ports for ADC. The specified ports become ADC targets.
    • TEH_ADC_SRC_VOLT: Power supply voltage
    • TEH_ADC_SRC_ADC_1-4: ADC1,2,3,4
  • u8InputRangeMask: Specifies the range (0-Vref or 0-2Vref) for the ADC target ports. Specified ports use 0-Vref; unspecified ports use 0-2Vref.
  • ai16Result[]: Structure for storing ADC values. Results are stored as mV values.
    • TEH_ADC_IDX_VOLT: Power supply voltage
    • TEH_ADC_IDX_ADC_1-4: ADC1,2,3,4

4.3 - AHI Functions and Explanations for DIO (GPIO)

Explanations of the TWENET library and AHI functions related to DIO (GPIO)
This section provides explanations of the TWENET library and AHI functions related to DIO (GPIO).

DIO (GPIO)

Some of the AHI functions related to DIO (GPIO) are implemented for source-level compatibility.

Overview

The pin assignment architecture differs from that of TWELITE BLUE/RED. Here, pins used in TWELITE BLUE/RED are labeled as DIO0..19/DO0..1/ADC0…3, while the pin names for the semiconductor used in TWELITE GOLD are labeled as PIO0..21. For details about the pins, refer to the semiconductor datasheet for each module.

  • Some pins on the module are not mapped one-to-one:
    • PIO0 is shared with DIO11 and DO0.
    • PIO14 is shared with DIO8 and ADC1.
  • Regarding DIO interrupts, there are the following differences:
    • DIO0..19 supported independent interrupts, but since this feature does not exist here, the GINT (group interrupt) feature is used to achieve similar behavior. (Another feature called PINT supports independent interrupts but only for up to four ports, so it is not used in this library.)
    • Hardware interrupt detection is only available on both edges; internal interrupts occur on either edge.
      • While running (not in sleep mode), whether to call the AHI interrupt handler is determined by the pin state after the interrupt occurs, so the fact that detection is on both edges is not apparent.
      • The edge for wake-up from sleep cannot be specified.

Pin Assignment

DIODIOPIONotes
DIO0016
DIO1117
DIO2218
DIO3319
DIO447
DIO556
DIO668
DIO779
DIO8814Shared with ADC1
DIO9912
DIO10104
DIO11110Shared with DO0
DIO121213
DIO13131
DIO141410
DIO151511
DIO161620
DIO171721
DIO18182
DIO19193
DO0 (PROG)0Shared with DIO11
DO15
ADC214Shared with DIO8
ADC115

AHIcmpt_Dio.cpp - Definitions and Constants

Definitions

#define BOARD_GPIO_PORT_MAX_PIN_COUNT 22 // Number of pins
#define BOARD_GPIO_PIN_TABLE_SIZE 24     // Rounded up to a multiple of 4 for 22 pins

g_twenet_ioport_remap_by_PIOn[]

const uint8 g_twenet_ioport_remap_by_PIOn[BOARD_GPIO_PIN_TABLE_SIZE];

(For internal library use) Table for converting PIO numbers to DIO numbers.

  • 0x80: SPIMISO pin
  • 0x90: ADC1 pin (analog only)
  • 0xFF: Unused / undefined

g_twenet_ioport_remap_by_AHIn[]

const uint8 g_twenet_ioport_remap_by_AHIn[BOARD_GPIO_PIN_TABLE_SIZE];

(For internal library use) Table for referencing PIO numbers from AHI numbers.

AHIcmpt_Dio.cpp - Definitions

Variables

uint32 G_TWENET_IOPORT_OUTPUT_BM() = 0;       // DIO bitmap for output ports
uint32 G_TWENET_IOPORT_INT_ENABLED_BM() = 0;      // DIO bitmap for interrupt-enabled ports
uint32 G_TWENET_IOPORT_INT_RISING_BM() = 0;       // DIO bitmap for rising-edge interrupt-enabled ports
uint32 G_TWENET_IOPORT_INT_FALLING_BM() = 0;      // DIO bitmap for falling-edge interrupt-enabled ports
volatile uint32 G_TWENET_IOPORT_INT_STATUS() = 0; // DIO bitmap recording wake-up pins when woken by DIO interrupt
uint32 G_TWENET_IOPORT_WAKE_STATUS() = 0;         // DIO bitmap storing I/O interrupt sources at wake-up
  • Each DIO bitmap corresponds bit n to DIOn (e.g., for DIO0 and DIO3, use (1UL << 0) | (1UL << 3)).

check_pio(), get_pio(), get_dio()

static inline bool check_pio(uint8 u8pio);
static inline uint8 get_pio(const uint8 u8dio);
static inline uint8 get_dio(const uint8 u8pio);
  • check_pio(): An inline function that checks whether the specified PIO number is valid and not already used by another peripheral.
  • get_pio(): Returns the PIO number corresponding to the specified DIO number. Returns 0xff if the assignment is invalid.
  • get_dio(): Returns the DIO number corresponding to the specified PIO number. Returns 0xff if the assignment is invalid.

s_gpio_int_handler()

static void s_gpio_int_handler(uint32 bm_pio, uint32 bm_pio_changed, void* p_data);

Interrupt handler function internally called when a DIO interrupt occurs.

  • If there is a pin change, interrupt information is sent via AppQAPI using __twenet_vAppQApiPostHwIntT().

AHIcmpt_Dio.cpp - AHI Function Definitions

vAHI_DioSetDirection()

void   vAHI_DioSetDirection(
    uint32      u32Inputs,
    uint32      u32Outputs);

Configures the input/output direction of ports.

  • In principle, ports are set to input state at initialization, but strictly speaking, the initial state is defined by the BOARD_InitPins() initialization in the TWENETmcu library’s pinmux.c.

vAHI_DioSetOutput()

void   vAHI_DioSetOutput( // u32On:HIGH, u32Off::LOW
    uint32      u32On,
    uint32      u32Off);

Changes the output state of ports. u32On is the DIO bitmap for pins to set HIGH, and u32Off is the DIO bitmap for pins to set LOW.

  • When multiple pins are specified, the changes are not simultaneous.
    • This is because, in the internal implementation, each pin is set individually within a loop.

vAHI_DioSetPullup()

void   vAHI_DioSetPullup(
    uint32      u32On,
    uint32      u32Off);

Configures the pull-up state.

  • In principle, the default is pull-up enabled, but strictly speaking, the initial state is defined by the BOARD_InitPins() initialization in the TWENETmcu library’s pinmux.c.

u32AHI_DioReadInput()

uint32 u32AHI_DioReadInput(void);

Retrieves the state of all ports at once.

  • The return value is a bitmap representing the state of all ports: bits set to 1 indicate HIGH level, and bits set to 0 indicate LOW level.
  • The values for non-existent DIO numbers or ports used by peripherals are undefined.

vAHI_DioWakeEnable()

void   vAHI_DioWakeEnable(
    uint32      u32Enable,
    uint32      u32Disable);

Starts DIO interrupts. u32Enable specifies the DIO bitmap for adding interrupt handling, and u32Disable specifies the DIO bitmap for removing interrupt handling. Additionally, you must specify the interrupt edge for the enabled pins using vAHI_DioWakeEdge().

  • The behavior is undefined when specifying pins that are not configured as inputs (e.g., output pins or pins assigned to other peripheral functions).

vAHI_DioWakeEdge()

void   vAHI_DioWakeEdge(
    uint32      u32Rising,
    uint32      u32Falling);

Configures the interrupt pins. This call sets both rising and falling edges for the specified pins at once. Note that you cannot add or remove edges individually.

Although the function name contains “Wake,” it configures both runtime interrupt handling and wake-up-from-sleep behavior.

  • If the same pin is specified for both u32Rising and u32Falling, interrupts occur on both edges due to the design principle. (However, since this is not a valid AHI setting, it is outside the scope of operation verification.)
  • During interrupt operation, vAHI_DioWakeEnable() is called internally for reconfiguration.
  • The behavior is undefined when specifying pins that are not configured as inputs (e.g., output pins or pins assigned to other peripheral functions).
  • For wake-up from sleep, the interrupt edge is always set to both edges.

u32AHI_DioWakeStatus()

uint32 u32AHI_DioWakeStatus(void);

Returns the bitmap of pins that triggered the wake-up during a DIO interrupt.

  • Internally, it returns the value of __twenet_ioport_int_status at the time of the call. After the call, the value is set to 0.

bAHI_DoEnableOutputs()

static inline bool_t bAHI_DoEnableOutputs(bool_t bEnableDO) {
	return bAHI_DoEnableOutputsEx_MW(bEnableDO, bEnableDO);
}

Configures the DO0 and DO1 pins as output.

  • Both DO0 and DO1 are configured as output.
  • To configure only one pin, call bAHI_DoEnableOutputsEx_MW().
    • DO1 (PIO5) is assigned to the pin used to determine transition to program mode (ISP_ENT) at startup, so it requires attention in hardware design. Unless there is a special reason, it is recommended to use a different pin.
  • DO0 (PIO0) is also assigned to DIO11, so if both are used, code adjustments (excluding control of one side) are required.

vAHI_DoSetDataOut()

void vAHI_DoSetDataOut(
    uint8       u8On,
    uint8       u8Off);

Configures output settings for DO0 (PIO0) and DO1 (PIO1).

  • DO0 is specified by bit0 (0x1), and DO1 is specified by bit1 (0x2) in the bitmap.
  • Setting a bit in u8On sets the output to HIGH level, while setting it in u8Off sets the output to LOW level.

vAHI_DoSetPullup()

 void vAHI_DoSetPullup(
    uint8       u8On,
    uint8       u8Off);

Does nothing.

AHIcmpt_Dio.cpp - AHI Extended API

Functions with the _MW suffix are custom extensions not present in the AHI library.

bAHI_DoEnableOutputsEx_MW()

bool_t bAHI_DoEnableOutputsEx_MW(
    bool_t bEnableDO0, bool_t bEnableDO1);

Configures DO0 and DO1 as outputs.
This function was added because bAHI_DoEnableOutputs() configures both ports simultaneously.

vAHI_DioInterruptDisablePinsIntWhenChanged_MW(), vAHI_DioInterruptReavtivate_MW()

void vAHI_DioInterruptDisablePinsIntWhenChanged_MW(bool_t bSet);
void vAHI_DioInterruptReavtivate_MW();

Temporarily disables interrupts for pins where an interrupt has been detected.

  • When called with bSet set to TRUE, interrupts for the affected pins are temporarily disabled when a DIO interrupt occurs.
  • For inputs such as mechanical buttons with significant chattering, enable this setting and call vAHI_DioInterruptReavtivate_MW() after a certain time has passed since the interrupt to resume interrupts.

vAHI_DioOnSleep_MW()

void vAHI_DioOnSleep_MW();

An internal processing function not intended to be called by users.
It handles DIO interrupt-related processing before entering sleep, specifically configuring the DIO wake-up pins.

vAHI_DioOnWakeup_MW()

void vAHI_DioOnWakeup_MW(bool_t b_init_2nd);

An internal processing function not intended to be called by users.
It handles DIO interrupt-related processing at wake-up and stores the pins that triggered the wake-up.

  • When called with b_init_2nd set to false, it runs at the very early stage of the WarmMain() process to identify the wake-up sources.
  • It is then called again with true just before the call to cbAppWarmStart(TRUE).

vAHI_DioRetentionRelease_MW()

void vAHI_DioRetentionRelease_MW();

Releases the DIO output state retention after waking up from sleep.
This function is used when waking from RAM-OFF sleep and inside cbAppColdStart().

On JN518X, the register setting (SYSCON->RETENTIONCTRL) to retain DIO output states is configured before entering sleep.
DIO pins with output settings retain their states as configured in the register, and after waking from sleep, the output states remain until the register settings are changed. Calling this function releases the output state retention.

To restore the same configuration as before sleep, call vAHI_DioSetDirection() or vAHI_DioSetOutput() before calling this function to explicitly configure the output settings. This is necessary because DIO internal registers are cleared during sleep.

After the call to cbAppColdStart(), the TWENETmcu library performs the same process as this function. To avoid unintended HI/LO transitions on ports, configure the port outputs inside cbAppColdStart().

Others

Notes When Not Using This Library

Do not call functions from this library. Even if you do not call them, this library still depends on the TWENETmcu and TWENETlib libraries.

Refer to the following to resolve dependencies:

  • Regarding interrupt pins when performing sleep procedures:
    • You need to adjust vAHI_DioOnSleep_MW() and vAHI_DioOnWakeup_MW().
      • These two functions are called from vAHI_OnSleep_MW() and vAHI_OnWakeup_MW() in TWENETcmpt.
    • The vAHI_OnSleep_MW() function depends on the closed-source TWENETlib library.
      • In vAHI_DioOnSleep_MW(), specify the PIO bitmap for wake-up interrupt detection in __twenet_ioport_int_status. It is applied inside ToCoNet_vSleep() to execute sleep properly.
    • vAHI_OnWakeup_MW() and vAHI_DioOnWakeup_MW() are called within the TWENETmcu library source. Modify the processing as needed.

4.4 - AHI Functions and Explanations for Timer (PWM)

Explanations of the TWENET library and AHI functions related to Timer (PWM)
This section provides explanations of the TWENET library and AHI functions related to Timer (PWM).

Timer (PWM)

Some parts of the AHI Timer-related APIs are implemented for source code compatibility.

AHI APIについて

vAHI_TimerFineGrainDIOControl()

void vAHI_TimerFineGrainDIOControl(uint8 u8BitMask)

Specifies the bitmask to disable output pins. Only the bits corresponding to TIMER_0 … TIMER_4 are valid.

  • Call this function before executing vAHI_TimerEnable().
  • Even if output is enabled in the parameters of vAHI_TimerEnable(), pins set to be disabled by this function will be treated as output-disabled.

vAHI_TimerAssignPIOPin_MW()

void vAHI_TimerAssignPIOPin_MW(
		uint8 u8_timer_id,
		uint8 u8_pin_id)

This function is specific to TWELITE GOLD.

Specifies the PIO number of the pin to be used with the specified timer device (u8_timer_id).

Each PIO number is linked to a specific PWM channel. Some PIO numbers do not support PWM. Depending on how you specify them, it is possible to create conflicting settings, such as using the same PWM channel multiple times. Refer to the pin assignment table for mapping between PIO numbers and PWM channels.

  • u8_timer_id specifies the target timer device (E_AHI_DEVICE_TIMER0-4).
  • Settings in vAHI_TimerFineGrainDIOControl() are also valid, but output enable/disable is controlled by bOutputEnable in vAHI_TimerEnable().
  • Even if output is disabled and only timer interrupts are used, specify the pin number corresponding to the PWM channel to be used.

This is a custom function of this library.

vAHI_TimerEnable()

void vAHI_TimerEnable(
    uint8       u8_timer_id,
    uint8       u8Prescale,
    bool_t      bIntRiseEnable,
    bool_t      bIntPeriodEnable,
    bool_t      bOutputEnable)

Enables the timer.

  • If bIntRiseEnable == TRUE, it is treated as bIntPeriodEnable == TRUE.
  • Even if bOutputEnable == TRUE is set, if the pin is disabled by vAHI_TimerFineGrainDIOControl(), it is treated as FALSE.
  • The behavior is undefined if this function is called again for a timer ID that has already been enabled.
When Hardware Resource Conflicts Occur

Due to hardware differences from TWELITE BLUE/RED, not all timer devices can be used in the same way. Refer to the pin assignment section described later for details.

  • If PWM output is enabled, software-based PWM output emulation will be performed.
  • If PWM output is disabled, the purpose is limited to timer interrupts, so the available PWM3 or PWM5 will be used without pin output.
  • No API or procedure is provided to check whether the above assignment has been made.

vAHI_TimerDisable()

void  vAHI_TimerDisable(uint8 u8_timer_id)

Disables the timer.

  • The output port is reverted to input (the pull-up setting is not changed).

vAHI_TimerDisable()

void  vAHI_TimerDisable(uint8 u8_timer_id)

Disables the timer.

  • The output port is reverted to input (the pull-up setting is not changed).

vAHI_TimerConfigure()

void vAHI_TimerConfigure(
		uint8       u8_timer_id,
		bool_t      bInvertPwmOutput,
		bool_t      bGateDisable)

Modifies the timer settings.

  • Configures bInvertPwmOutput.
  • bGateDisable is ignored.

vAHI_TimerStartRepeat()

void  vAHI_TimerStartRepeat(
		uint8       u8_timer_id,
	    uint16      u16Hi,
	    uint16      u16Lo)

Starts the timer.

  • This function can also be called while the timer is running and is used to change the PWM duty cycle settings.

vAHI_TimerStop()

void  vAHI_TimerStop(uint8 u8_timer_id)

Stops the timer.

vAHI_TimerSetLocation()

void vAHI_TimerSetLocation(
		uint8 u8Timer,
		bool_t bLocation,
		bool_t bLocationOverridePWM3andPWM2)

Changes the pin assignment.

  • Call this function before executing vAHI_TimerEnable().

vAHI_TimerXRegisterCallback

PUBLIC void  vAHI_Timer0RegisterCallback(
    PR_HWINT_APPCALLBACK        prTimer0Callback);
PUBLIC void  vAHI_Timer1RegisterCallback(
    PR_HWINT_APPCALLBACK        prTimer1Callback);
PUBLIC void vAHI_Timer2RegisterCallback(
    PR_HWINT_APPCALLBACK        prTimer2Callback);
PUBLIC void vAHI_Timer3RegisterCallback(
    PR_HWINT_APPCALLBACK        prTimer3Callback);
PUBLIC void vAHI_Timer4RegisterCallback(
    PR_HWINT_APPCALLBACK        prTimer4Callback);

The interrupt handler registration functions are not implemented. The interrupt handler is invoked via AppQAPI.

If you want to define a custom interrupt handler, implement the WEAK-defined handler functions below.
Refer to the implementation in AHIcmpt_TImers.cpp.
At a minimum, you need to call PWM_ClearStatusFlags(PWM, kPWM_PwmX);.

WEAK void PWM0_DriverIRQHandler(void); // MONO WIRELESS, DEFINED AS WEAK FUNCTION.
WEAK void PWM1_DriverIRQHandler(void);
WEAK void PWM2_DriverIRQHandler(void);
WEAK void PWM3_DriverIRQHandler(void);
WEAK void PWM4_DriverIRQHandler(void);
WEAK void PWM5_DriverIRQHandler(void);
WEAK void PWM6_DriverIRQHandler(void);
WEAK void PWM7_DriverIRQHandler(void);
WEAK void PWM8_DriverIRQHandler(void);
WEAK void PWM9_DriverIRQHandler(void);

Other Functions

void vAHI_TimerClockSelect(
    uint8       u8Timer,
    bool_t      bExternalClock,
    bool_t      bInvertClock);
void vAHI_TimerStartSingleShot(
    uint8       u8Timer,
    uint16      u16Hi,
    uint16      u16Lo);

These are either undefined functions or dummy functions that do nothing.

About Output Pins

  • Output pins are initialized for PWM use when calling vAHI_TimerEnabled().
  • Output pins are reset to input ports (without changing pull-up settings) when calling vAHI_TimerDisable().

About Interrupts

Interrupts at intermediate output transition points within a cycle are not supported. Only interrupts for each full cycle are supported.

Interrupt Handlers

Interrupt handlers are only supported in the standard TWENET callbacks cbToCoNet_u8HwInt() and cbToCoNet_vHwEvent(). Additional handlers cannot be registered.

If you want to define individual handlers, define the PWMx_IRQHandler() functions separately. In this case, events will not be reported to TWENET from the defined handler.

Pin Assignment

Pin assignment can be configured individually for each TIMER_ID, but due to hardware differences in TWELITE BLACK, assignments may be difficult in some cases.

Standard

AHI TIMER ID01234
SMD PIN##1216131519
AHI DIO##1011121317
PIO##4013121
PWM channel40219

When Using DO1,2 in Standard Mode

AHI TIMER ID01234
SMD PIN##12161219
AHI DIO##1011DO0DO117
PIO##400521
PWM channel400N/A9
  • TIMER_1 and TIMER_2 assignments conflict.
  • The output pin for TIMER_3 does not have hardware timer functionality.

Secondary Assignment

AHI TIMER ID01234
SMD PIN##678910
AHI DIO##45678
PIO##768914
PWM channel76891

When Using DO1,2 in Secondary Assignment

AHI TIMER ID01234
SMD PIN##671910
AHI DIO##45DO0DO18
PIO##760514
PWM channel760N/A1
  • The output pin for TIMER_3 does not have hardware timer functionality.

Others

Behavior When Pin Assignment Conflicts Occur

  • If a pin configured for PWM output has a conflict (e.g., the pin does not support PWM), software emulation will be used.
    • The software emulation controls the output under the system timer (SysTick) interrupt, using 16 clocks per cycle. If running at 1 kHz, the PWM period is 1000/16 ≈ 62 Hz.
  • If a pin without PWM output configured has a conflict (e.g., duplicate PWM device numbers), the available PWM3 or PWM5 is assigned. PWM interrupts will operate even without pin output.

When Not Using This Library’s PWM Features

  • Do not call AHI timer-related APIs (?AHI_Timer???).
    • Calling these APIs creates processing objects for AHI compatibility. Behavior is undefined if you then call APIs defined in fsl_pwm.h in this state.
  • Define PWM0_IRQHandler()PWM9_IRQHandler() separately. Since these are specified with weak linkage, your application’s non-weak definitions will take precedence at link time.

Behavior on Wake from Sleep

  • For RAM-retention sleep, the PWM output state immediately before sleep is restored. For RAM-off sleep, normal DIO initialization is performed.
void vAHI_TimerFineGrainDIOControl(
    uint8 u8BitMask);
PUBLIC void vAHI_TimerConfigure(
    uint8       u8Timer,
    bool_t      bInvertPwmOutput,
    bool_t      bGateDisable);
PUBLIC void  vAHI_TimerEnable(
    uint8       u8Timer,
    uint8       u8Prescale,
    bool_t      bIntRiseEnable,
    bool_t      bIntPeriodEnable,
    bool_t      bOutputEnable);
PUBLIC void  vAHI_TimerDisable(
    uint8       u8Timer);
PUBLIC void  vAHI_TimerClockSelect(
    uint8       u8Timer,
    bool_t      bExternalClock,
    bool_t      bInvertClock);
PUBLIC void  vAHI_TimerStartRepeat(
    uint8       u8Timer,
    uint16      u16Hi,
    uint16      u16Lo);
PUBLIC void  vAHI_TimerStop(
    uint8 u8_timer_id);
PUBLIC void vAHI_TimerSetLocation(
    uint8 u8Timer,
    bool_t bLocation,
    bool_t bLocationOverridePWM3andPWM2);

※ Some function names are redefined by macros.
※ The timer library in utils.h also uses the above APIs.

Example Handler Definitions

Minimal definitions including the essential steps.

void PWM0_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm0); }
void PWM1_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm1); }
void PWM2_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm2); }
void PWM3_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm3); }
void PWM4_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm4); }
void PWM5_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm5); }
void PWM6_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm6); }
void PWM7_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm7); }
void PWM8_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm8); }
void PWM9_IRQHandler(void) { PWM_ClearStatusFlags(PWM, kPWM_Pwm9); }
  • When you define these functions, interrupts/events will not be forwarded to TWENET.

About This Library’s Implementation

  • The main implementation code is in AHIcmpt_Timer.cpp.
  • The above code references _periph_pwm.hpp and _periph_pwm.cpp. These are class libraries that consolidate procedures using the platform drivers (driver/fs_???).

4.5 - Explanation of SMBus.c,h Defining SMBUS (I2C)-Related Procedures

Explanations of the TWENET library: SMBUS (I2C)-related procedures defined in SMBus.c,h
This section provides explanations of the TWENET library and the SMBUS (I2C)-related procedures defined in SMBus.c and SMBus.h.

SMBUS (I2C)

In many sample and application codes using TWENET, the I2C bus is typically not accessed directly through the low-level AHI library procedures.
Instead, a set of simplified read/write functions defined in SMBus.c and SMBus.h is used.

The following is a list of the function names provided:

void vSMBusInit(void);
void vSMBusInit_setClk(uint32 u32Clk);
void vSMBusDeInit();
void vSMBusDeInit(void);
bool_t bSMBusWrite(uint8 u8Address, uint8 u8Command,
						  uint8 u8Length, uint8* pu8Data);
bool_t bSMBusSequentialRead(uint8 u8Address, uint8 u8Length,
		   uint8* pu8Data);

SMBus.c SMBus.h

These are a set of functions summarizing typical I2C procedures, with source code stored in TWENETmwx/source/sensors/legacy.

  • If the TWENETmwx library is not linked (C project), copy and use this source code.

vSMBusInit()

void vSMBusInit(void);

Initializes the I2C bus.
The pins used are DIO14 (CLK) and DIO15 (DATA), with a clock frequency of 100 Kbps.

vSMBusInit_setClk(uint32)

{{{cpp {noln=true} void vSMBusInit_setClk(uint32 u32Clk); }}}

Using this function instead of vSMBusInit() initializes the I2C bus with the clock specified by u32clk.

  • If u32clk >= 7 and u32clk <= 255 ⇒ Initializes with clock frequency 3200000ul / (u32clk + 1). For example, specifying 31 gives 100 kHz, and 7 gives 400 kHz.
  • If u32clk >= 12500 and u32clk <= 400000 ⇒ Initializes with u32clk directly.
  • Otherwise ⇒ Undefined behavior.

※ The actual frequency will be the closest available based on the hardware clock divisor. For detailed calculations, refer to the source code (for TWELITE GOLD, see NXP’s FSL library specifications).

// Implementation for TWELITE GOLD
PUBLIC void  TWENET_smbus_vSMBusInit_setClk(uint32_t u32clk)
{
    ...
	if (u32clk >= 7 && u32clk <= 255) { // given by divisor
		u32clk = 3200000ul / (u32clk + 1);
	}

	if (u32clk < 12500ul || u32clk > 400000ul) {
		u32clk = 100000ul;
	}

	// initialize the I2C
    //... rest of the implementation
      _conf.baudRate_bps = u32clk;
      I2C_MasterGetDefaultConfig(&_conf); // FSL library function
}

// Implementation for TWELITE BLUE/RED
void vSMBusInit_setClk(uint32 u32Clk)
{
    /* convert clock to clock divisor */
    if (u32Clk > 255) {
    	u32Clk = (3200000UL / u32Clk) - 1;
    }
    if (u32Clk < 7 || u32Clk > 255) u32Clk = 31; // set 100kHz

    /* run bus at specified value */
    vAHI_SiMasterConfigure(TRUE, FALSE, u32Clk);
    // 16/[(PreScaler + 1) x 5]MHz
    //		--> 31:100KHz, 7:400KHz, 47:66KHz
}

vSMBusDeInit()

void vSMBusDeInit();

Stops the use of the I2C bus.

  • For TWELITE BLUE/RED, calls vAHI_SiMasterDisable().
  • For TWELITE GOLD, stops the I2C bus usage and restores DIO14 and DIO15 pins to the TWENET library’s initial configuration (input ports with pull-up).

bSMBusWrite()

bool_t bSMBusWrite(
	uint8 u8Address,
    uint8 u8Command,
	uint8 u8Length,
    uint8* pu8Data)

Performs a write operation on the I2C bus.

  • u8Address ⇒ Specifies the device address on the I2C bus.
  • u8Command ⇒ Specifies the command (first transfer byte) for the write operation.
  • u8Length ⇒ Number of subsequent bytes. If 0, only the command byte is transferred. If greater than 0, pu8Data must be defined.
  • pu8Data ⇒ Pointer to the memory area containing the bytes to be transferred.

Returns TRUE if the transfer succeeds, and FALSE if it fails.

bSMBusSequentialRead()

bool_t bSMBusSequentialRead(
    uint8 u8Address,
    uint8 u8Length,
	uint8* pu8Data)

Performs a read operation on the I2C bus.

  • u8Address ⇒ Specifies the device address on the I2C bus.
  • u8Length ⇒ Specifies the number of bytes to read (must be 1 or more).
  • pu8Data ⇒ Pointer to the memory area where the read bytes will be stored.

Returns TRUE if the transfer succeeds, and FALSE if it fails.

Others

Handling During Sleep

  • For TWELITE BLUE/RED, hardware reinitialization is required after waking from sleep.
    If vSMBusDeInit() is not called, the pin state is undefined (or follows the JN516x peripheral specification).
    You can reinitialize by calling vSMBusInit() or vSMBusInit_setClk() again.

  • For TWELITE GOLD, the behavior is as follows:

    • RAM ON (normal) sleep: If the I2C bus was initialized before sleep, it will be reinitialized upon waking. If the I2C bus was not in use, normal general-purpose IO wake-up handling will apply.
    • RAM OFF (deep) sleep: Upon waking, TWENET will reinitialize the pins as input pins with pull-up enabled.

TWELITE GOLD Implementation

AHI-compatible functions are not provided; instead, corresponding functions are implemented in SMBus.c and SMBus.h.

// Implementations in the TWENETcmpt library
PUBLIC void TWENET_smbus_vSMBusInit(void);
PUBLIC void TWENET_smbus_vSMBusDeInit(void);
PUBLIC void TWENET_smbus_vSMBusInit_setClk(uint32 u32clk);
PUBLIC bool_t  TWENET_smbus_bSMBusWrite(uint8 u8Address,
    uint8 u8Command, uint8 u8Length, uint8* pu8Data);
PUBLIC bool_t TWENET_smbus_bSMBusSequentialRead(uint8 u8Address,
    uint8 u8Length,  uint8* pu8Data);

// SMBus.h uses inline definitions to call the above functions
static inline void vSMBusInit(void) {
	TWENET_smbus_vSMBusInit();
}
static inline void vSMBusInit_setClk(uint32 u32Clk) {
	TWENET_smbus_vSMBusInit_setClk(u32Clk);
}
static inline void vSMBusDeInit() {
	TWENET_smbus_vSMBusDeInit();
}
static inline void vSMBusDeInit(void) {
	TWENET_smbus_vSMBusInit();
}
static inline bool_t bSMBusWrite(uint8 u8Address, uint8 u8Command,
						  uint8 u8Length, uint8* pu8Data) {
	return TWENET_smbus_bSMBusWrite(u8Address, u8Command, u8Length, pu8Data);
}
static inline bool_t bSMBusSequentialRead(uint8 u8Address, uint8 u8Length,
		   uint8* pu8Data) {
	return TWENET_smbus_bSMBusSequentialRead(u8Address, u8Length, pu8Data);
}

4.6 - AHI Functions and Explanations for SPI

Explanations of the TWENET library and AHI functions related to SPI
This section provides explanations of the TWENET library and AHI functions related to SPI.

SPI

This section covers the implementation of AHI-compatible functions for SPI.

The following pins are used for SPI operation:

SignalPin Name (PIO No.)Description
SCKSPLCLK=DIO11(PIO0)Clock signal
This pin is shared with SPICLK and DIO11
MOSIDIO18(PIO2)SPIMOSI. Output from TWELITE side, input to external SPI device.
MISOSPIMISO(PIO5)SPIMISO. Input to TWELITE side, output from external SPI device.
SEL0DIO19(PIO3)
SEL1DIO0(PIO16)
SEL2DIO1(PIO17)

When using alternate pin assignments (set via vAHI_SpiSetLocation_MW(FALSE)):

SignalPin Name (PIO No.)Description
SCKADC1(PIO15)Clock signal
MOSIDIO1(PIO17)SPIMOSI. Output from TWELITE side, input to external SPI device.
MISODIO2(PIO18)SPIMISO. Input to TWELITE side, output from external SPI device.
SEL0DIO0(PIO16)
SEL1DIO8=ADC2(PIO14)This pin is shared with DIO8 and ADC2
SEL2DIO12(PIO13)

SPI operates using hardware functionality, so there may be some differences in pin behavior (especially the HIGH/LOW state when no transfer is occurring).

  • The implementation uses blocking transfers. To maintain code compatibility, ensure to include polling wait code immediately after transfer API calls (bAHI_SpiPollBusy(), vAHI_SpiWaitBusy()).

vAHI_SpiConfigure()

void   vAHI_SpiConfigure(
    uint8       u8SlaveEnable,
    bool_t      bLsbFirst,
    bool_t      bPolarity,
    bool_t      bPhase,
    uint8       u8ClockDivider,
    bool_t      bInterruptEnable,
    bool_t      bAutoSlaveSelect);

Initializes the SPI.

  • bInterruptEnable is not supported; this parameter is ignored.

vAHI_SpiDisable()

void vAHI_SpiDisable(void);

Stops the use of SPI.

vAHI_SpiSelect()

void   vAHI_SpiSelect(
    uint8       u8SlaveMask)

Selects the SPI SELECT pin.

  • If bAutoSlaveSelect in vAHI_SpiConfigure() is set to TRUE, specifies the pin to control but does not control it at the time of this call.
  • If bAutoSlaveSelect in vAHI_SpiConfigure() is set to FALSE, controls the SELECT pin (sets the target pin LOW, all others HIGH).

vAHI_SpiStop()

PUBLIC void   vAHI_SpiStop(void);

Deselects the SELECT pin.
Performs the same operation as vAHI_SpiSelect(0).

vAHI_SpiStartTransfer()

void vAHI_SpiStartTransfer(
    uint8       u8CharLen,
    uint32      u32Out);

void   vAHI_SpiStartTransfer32(uint32 u32Out);
void   vAHI_SpiStartTransfer16(uint16 u16Out);
void   vAHI_SpiStartTransfer8(uint8 u8Out);

Executes an SPI transfer.

  • This process runs in blocking mode.
  • If the bit length is not a multiple of 8, the transfer will be split into 2–3 parts.
  • When specifying 32-bit transfers, regardless of the memory byte order (endianness), data is sent from the most significant byte to the least significant byte.
    As a result, the transfer waveform will be identical on both BLUE and GOLD.

AHI_SpiReadTransfer()

static inline uint32 u32AHI_SpiReadTransfer32(void);
static inline uint16 u16AHI_SpiReadTransfer16(void);
static inline uint8  u8AHI_SpiReadTransfer8(void);

Call this after the transfer completes to return the read value.

bAHI_SpiPollBusy()

bool_t bAHI_SpiPollBusy(void);
inline void vAHI_SpiWaitBusy(void) { while(bAHI_SpiPollBusy()); }

Always returns FALSE because the transfer API performs blocking transfers.

bAHI_SpiTransferBlocking_MW()

bool_t bAHI_SpiTransferBlocking_MW(
    uint8       *au8tx,
	uint8       *au8rx,
	uint8		u8len);

Performs byte-level SPI transfers.
au8tx is the transmit data array, au8rx is the receive data array, and u8len is the number of bytes to transfer.

  • Data is transferred sequentially from the beginning of the array.
    To transfer from LSB first, store the LSB-side bytes first in the array. The same applies to the received data.

vAHI_SpiWaitBusy()

void vAHI_SpiWaitBusy(void);

Returns immediately.

vAHI_SpiSetLocation_MW()

void vAHI_SpiSetLocation_MW(bool_t bLocation);

Changes the pin assignment configuration.
If using the default pin assignments, calling this function is unnecessary.
If using the alternate pins, call this function before invoking vAHI_SpiConfigure().

  • bLocation == FALSE (default) → Uses the default pin assignments.
  • bLocation == TRUE → Uses the alternate pin assignments.

Others

Transfer Splitting

When performing transfers with vAHI_SpiStartTransfer() that are not a multiple of 8 bits (e.g., 8, 16, 24, 32 bits),
the transfer is internally split into two parts.
As a result, the waveform will be held for a certain period between the first and second transfers.

Behavior on Wake from Sleep

If the SPI bus was initialized before entering RAM-retention sleep, the initialization state will be restored upon wake-up. For RAM-off sleep, normal DIO initialization will be performed at startup.

To improve code compatibility with BLUE/RED, explicitly call vAHI_SpiDisable() before sleep.

4.7 - AHI Functions and Explanations for Random Numbers

Explanations of the TWENET library and AHI functions related to random numbers
This section provides explanations of the TWENET library and AHI functions related to random numbers.

Random (Random Numbers)

Implementation of AHI-compatible functions related to random number generation.

vAHI_Start|StopRandomNumberGenerator()

void vAHI_StartRandomNumberGenerator(bool_t const bMode, bool_t const bIntEn);
void vAHI_StopRandomNumberGenerator(void);

Starts or stops random number generation.

u16AHI_ReadRandomNumber()

uint16 u16AHI_ReadRandomNumber(void);

Reads a 16-bit random value.

  • If random number generation has not been started, returns 57005.

u32AHI_ReadRandomNumber_MW()

uint32 u32AHI_ReadRandomNumber_MW(void);

(TWELITE GOLD only) Reads a 32-bit random value.

  • If random number generation has not been started, returns 3735928559.

vAHI_ReinitRandomNumberGenerator_MW()

void vAHI_ReinitRandomNumberGenerator_MW();

(TWELITE GOLD only) Reinitializes the random number generator device.

4.8 - AHI Functions and Explanations for UART

Explanations of the TWENET library and AHI functions related to UART
This section provides explanations of the TWENET library and AHI functions related to UART.

UART

UART usage relies on serial.c, .h and uart.c, .h found in TWENETutils.
This section explains AHI-compatible functions with behaviors specific to TWELITE GOLD.

  • When using UART1, you must call vAHI_UartSetLocation() or vAHI_UartSetLocationByPio_MW() to specify the assigned ports beforehand.
  • UART0 does not require any special procedure like UART1 for usage.

vAHI_UartSetLocation()

void vAHI_UartSetLocation(uint8_t u8port, bool_t bSel);

Specifies the port assignment for UART.

  • Does not affect UART0 assignment; it cannot be changed from the default ports (DIO6,7).
  • Two assignment options are available for UART1.
  • This function must be called when using UART1.
  • To assign other options for UART1, use vAHI_UartSetLocationEx_MW().
bSelTXRX
FALSEDIO14(PIO10)DIO15(PIO11)
TRUEDIO11(PIO0)*1DIO13(PIO1)

*1 This overlaps with the default SPICLK pin.

vAHI_UartSetLocationByPio_MW()

void vAHI_UartSetLocationByPio_MW(uint8_t u8port, uint8 u8TxPort, uint8 u8RxPort)

Assigns ports for UART.
Specify E_AHI_UART_1 for u8port.
Set the PIO numbers for the TX and RX ports using u8TxPort and u8RxPort.

Available PIO numbers (DIO numbers):

  • TX: 0 (DO0, DIO11), 6 (DIO5), 10 (DIO14), 20 (DIO16)
  • RX: 7 (DIO4), 1 (DIO13), 11 (DIO15), 19 (DIO13)

vAHI_UartDisable()

void vAHI_UartDisable(uint8_t u8port)

Disables the UART port specified by u8port.
The pin state will return to its initial configuration as defined in TWENETmcu/board/pin_mux.c at startup.

4.9 - AHI Functions and Explanations for WatchDog (WDT)

Explanations of the TWENET library and AHI functions related to WatchDog (WDT)
This section provides explanations of the TWENET library and AHI functions related to WatchDog (WDT).

WatchDog(WDT)

vAHI_WatchdogStart()

void vAHI_WatchdogStart(uint8 u8Prescale);

Starts the Watchdog Timer (WDT).

  • The timeout period is set approximately. Specifically, when u8Prescale == 0, the timeout is 8 ms; otherwise, it is set as ((1UL << (u8Prescale - 1)) + 1) * 8 ms, passed to the_wwdt->init().
  • If a value outside the valid range (u8Prescale > 12) is specified, u8Prescale = 10 (about 4 seconds) will be used.
  • When compiled with -DDEBUG, this process is skipped, and the WDT remains stopped.

vAHI_WatchdogStop()

void vAHI_WatchdogStop();

On TWELITE GOLD, once started, the watchdog cannot be stopped.
This function is called when changing the watchdog timer’s timeout period, as shown below:

...
vAHI_WatchdogStop(); // Calls the stop API (actually does not stop)
vAHI_WatchdogStart(12); // Reconfigures to approximately 16 seconds

vAHI_WatchdogRestart()

void   vAHI_WatchdogRestart();

Call this before the watchdog timer times out.

  • When compiled with -DDEBUG, this process is skipped.

4.10 - AHI Functions and Explanations for WakeTimer

Explanations of the TWENET library and AHI functions related to WakeTimer

WakeTimer

Implementation of vAHI_WakeTimer-related compatible functions.

The Wake Timer has two channels, both running continuously regardless of sleep state.
The counter operates in a decrementing manner, generating an interrupt when it reaches zero.
Additionally, since the wake timer keeps running, it can be used as a clock to measure elapsed time since startup.
For this purpose, a set of FRWT (Free Running WTimer) functions is also provided.

  • Timer width: E_AHI_WAKE_TIMER_0 = 41-bit, E_AHI_WAKE_TIMER_1 = 28-bit.
    The latter differs from BLUE/RED (JN516x); note that the maximum count value is 0x0FFFFFFF when calculating time differences.
    For example, to compute elapsed counts between ct1 and ct2, use (((ct2 << 4) - (ct1 << 4)) >> 4).
  • This library does not provide functions handling timer values exceeding 32 bits.
  • In the mwx library and some applications, one timer (E_AHI_WAKE_TIMER_0) is used continuously for time measurement through the Free Running WTimer (FRWT) API.

vAHI_WakeTimerEnable()

void vAHI_WakeTimerEnable(uint8 u8Timer,
						  bool_t bIntEnable)

Initializes the timer.

vAHI_WakeTimerStart()

void vAHI_WakeTimerStart(uint8 u8Timer, uint32 u32Count)

Starts the timer.
u32Count specifies the counter value.
For TWELITE GOLD, to trigger an interrupt after 1 second, specify 32768 (the frequency of the 32KHz crystal oscillator).

vAHI_WakeTimerStop()

void vAHI_WakeTimerStop(uint8 u8Timer)

Stops the timer.

u32AHI_WakeTimerCalibrate()

uint32 u32AHI_WakeTimerCalibrate(void);

Returns the wake timer calibration value 10000.

  • Normally, with a low-precision RC timer, this value would vary by about ±30%, but since TWELITE GOLD uses a 32KHz crystal-based timer circuit, this calibration is unnecessary, and the function always returns 10000.

u32AHI_WakeTimerRead()

uint32 u32AHI_WakeTimerRead(uint8 dev)

Returns the counter value. The wake-up interrupt occurs when the counter reaches zero. Afterward, the counter continues decrementing (after 0, it rolls over to the maximum value).

u8AHI_WakeTimerStatus()

uint8 u8AHI_WakeTimerStatus(void)

Returns the bitmap indicating the timer status.
E_AHI_WAKE_TIMER_0E_AHI_WAKE_TIMER_MASK_0 (1)
E_AHI_WAKE_TIMER_1E_AHI_WAKE_TIMER_MASK_1 (2)

u8AHI_WakeTimerFiredStatus()

uint8 u8AHI_WakeTimerFiredStatus()

Used immediately after wake-up.
If the wake-up source is WTIMER, a non-zero value is returned.

  • For E_AHI_WAKE_TIMER_0, returns E_AHI_WAKE_TIMER_MASK_0 (1).
  • For E_AHI_WAKE_TIMER_1, returns E_AHI_WAKE_TIMER_MASK_1 (2).

Free Running WTimer (FRWT)

Uses one channel of the WAKE TIMER (typically E_AHI_WAKE_TIMER_0) as a continuously running real-time counter. This allows time measurement regardless of the sleep state.

Global Variables

G_TWENET_FREE_RUNNING_WTIMER_ENABLED()

uint8_t G_TWENET_FREE_RUNNING_WTIMER_ENABLED() // MACRO

This variable is set in the cbAppColdStart(FALSE) call. Specify 0x80 to operate E_AHI_WAKE_TIMER_0 as FRWT. While the WAKE TIMER counter decrements over time, FRWT increments.

  • In the mwx library, FRWT with E_AHI_WAKE_TIMER_0 is automatically configured.

g_twenet_free_running_wtimer_boot_tick

uint32_t g_twenet_free_running_wtimer_boot_tick

Stores the counter value immediately after waking from sleep (with RAM retention). This is set when vAHI_FRWTSetBootCount_MW() is called from within the TWENET library.

vAHI_FRWTStart_MW()

void vAHI_FRWTStart_MW(uint8_t u8Timer)

This function is primarily used within the TWENET library and should not be used in user programs. FRWT is started based on the setting of the global variable G_TWENET_FREE_RUNNING_WTIMER_ENABLED().

u32AHI_FRWTGetCurrentCount_MW()

uint32 u32AHI_FRWTGetCurrentCount_MW()

Returns the FRWT counter value (32000 counts/second).

u32AHI_FRWTGetCurrentCount_msec_MW()

uint32 u32AHI_FRWTGetCurrentCount_msec_MW(uint32* dec_part)

Returns the current FRWT count in milliseconds.

  • dec_part specifies either NULL or a pointer to a uint32 variable.
    If provided, it returns the value in 1/10 millisecond units (0..9).

u32AHI_FRWTConvertCount_msec_MW()

static inline uint32 u32AHI_FRWTConvertCount_msec_MW(uint32 ct, uint32* dec_part) {
	// note: see wtimer::freerun_ct_convert_msec()
	uint64_t v = 1000ull * ct;
	if(dec_part) *dec_part = (10*(v & 32767)) >> 15;
	return (uint32)(v >> 15);
}

Converts the FRWT counter value to milliseconds.
If dec_part is specified, it returns the value in 1/10 millisecond units (0..9).

i32AHI_FRWTCompareCount_MW()

int32 i32AHI_FRWTCompareCount_MW(uint32 val_past, uint32 val_now)

Compares FRWT counter values. Specify val_now as the more recent value and val_past as the older value. In this case, the function returns a positive count value.

i32AHI_FRWTCompareCount_msec_MW()

int32 i32AHI_FRWTCompareCount_msec_MW(uint32 val_past, uint32 val_now)

Compares FRWT counter values.
Specify val_now as the more recent value and val_past as the older value.
In this case, the function returns the positive value in milliseconds.

vAHI_FRWTSetBootCount_MW()

void vAHI_FRWTSetBootCount_MW()

This function is primarily used within the TWENET library and should not be used in user programs.

It is used to save the FRWT counter value when waking up from sleep (with RAM retention, warm boot).

uint32 u32AHI_FRWTGetBootCount_MW()

uint32 u32AHI_FRWTGetBootCount_MW()

Returns the FRWT counter value when waking up from sleep (with RAM retention, warm boot).

u32AHI_FRWTGetBootCount_msec_MW()

uint32 u32AHI_FRWTGetBootCount_msec_MW()

Converts and returns the FRWT counter value in milliseconds when waking up from sleep (with RAM retention, warm boot).

4.11 - AHI Functions and Explanations for Onchip Temp Sensor

Explanations of the TWENET library and AHI functions related to the Onchip temp sensor

Onchip Temp Sensor

In TWELITE GOLD, a temperature sensor is implemented inside the chip.
The sensor value is used as a parameter for initializing the wireless MAC layer.

Handling of Temperature Sensor During MAC Layer Initialization

  • If the temperature sensor value cannot be obtained, initialization is performed with a default value of 20°C.
  • If more than G_TWENET_CHIPSENSOR_ADC_INTERVAL_MS() milliseconds have elapsed when waking up from sleep (RAM retained), the temperature is measured again at wake-up, and the MAC layer is reinitialized based on the sensor value.

Global Variables

uint8 G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
// Macro for variable access

A configuration variable to automatically acquire the temperature sensor value. Set it in cbAppColdStart(FALSE).

SettingDescriptionNotes
0Do not automatically acquire the temperature sensor value.MAC layer temperature correction uses a fixed value (20°C).
1Automatically acquire the temperature sensor value.
uint8_t G_TWENET_CHIPSENSOR_ADC_TIMES_SCALER()
// Macro for variable access
SettingADC Count
01
12
24
38

Specifies the scaler value corresponding to the number of ADC measurements for the temperature sensor.

int32 G_TWENET_CHIPSENSOR_TEMP128TH()
// Macro for variable access

Stores the temperature measured by the chip sensor in the TWENET library (value in °C multiplied by 128).

int16 g_twenet_chipsensor_volt_on_boot;

TWENET library stores the measured voltage value [mV].
This value is recorded at the same time as the temperature sensor measurement.

uint32 G_TWENET_CHIPSENSOR_ADC_INTERVAL_MS()
  = (10*60*1000ul)
// Macro for variable access

If the time elapsed since the last measurement is within the period specified by this variable, the temperature sensor reading will be skipped.
Set this in cbAppColdStart(FALSE).

uint8 g_twemet_chipsensor_capture_this_time;

An internal flag that determines whether to perform a temperature measurement at boot.

bAHI_AdcTemp_Measure_MW()

bool_t bAHI_AdcTemp_Measure_MW(
    int32 *i32temp_128th,
    int16 *i16volt_mv,
    uint8 adc_times_scaler,
    bool_t bTurnOnSensor)

Performs the temperature sensor measurement.

  • i32temp_128th is a pointer to an int32 variable that stores the temperature measurement result.
  • i16volt_mv is the power supply voltage [mV] measured at the same time.
  • adc_times_scaler specifies the scaler value corresponding to the number of ADC measurements for the temperature sensor. For configuration values, refer to the explanation of G_TWENET_CHIPSENSOR_ADC_TIMES_SCALER().
  • If bTurnOnSensor is set to TRUE, the function powers on the temperature sensor and performs the required waiting process. If set to FALSE, you must call vAHI_AdcTemp_TurnOn_MW() beforehand and ensure the required wait time has passed.

vAHI_AdcTemp_TurnOn_MW()

void vAHI_AdcTemp_TurnOn_MW()

Powers on the temperature sensor. A waiting time of 100 μs is required after this call.

uint32 u32AHI_AdcTemp_GetCaptTick_MW()

uint32 u32AHI_AdcTemp_GetCaptTick_MW()

Returns the FRWT timestamp of the last temperature sensor measurement in 32KHz count units.

uint32 u32AHI_AdcTemp_GetCaptTick_msec_MW()

uint32 u32AHI_AdcTemp_GetCaptTick_msec_MW()

Returns the FRWT timestamp of the last temperature sensor measurement in milliseconds.

u32AHI_AdcTemp_ElapsedFromCapt_msec_MW(), u32AHI_AdcTemp_TickrefFromCapt_msec_MW()

uint32 u32AHI_AdcTemp_ElapsedFromCapt_msec_MW()
uint32 u32AHI_AdcTemp_TickrefFromCapt_msec_MW(uint32 tick_ref)

Returns the elapsed time in milliseconds since the last temperature measurement.

5 - TWENETeastl - EASTL Library

Implementation of C++ STL with static memory allocation
Additional explanation about the EASTL library.

TWENETeastl - EASTL Library

EASTL is a standard template library (containers and algorithms) maintained by Electronic Arts. It is implemented following C++ STL (Standard Template Library) but was developed with the constraints of game console environments in mind, providing containers and algorithms designed for systems with strict memory usage limitations.

This library enables the use of EASTL within TWENET.

Key features include:

  • Fixed-memory containers (fixed_):
    Containers with a fixed number of elements that do not perform dynamic allocation. If declared globally, memory is allocated at compile time; if declared locally, memory is allocated on the stack and available within that scope.

  • Intrusive containers:
    Unlike normal containers that can store arbitrary data structures, intrusive containers require inheriting a base class to maintain link information within the data structure itself.
    While this restricts container usage to specific data structures, it greatly improves memory efficiency for lists or maps.
    (Reference: Intrusive and non-intrusive containers)

The 2007 article EASTL (open-std.org) describes the motivation behind its development.
(Additional articles: EASTL and Game Development, Part 1, Part 2)

EASTL Library Documentation

Please refer to the HTML files under the doc directory.

The README.md and CONTRIBUTING.md files, originally located in the root directory of the distribution,
have been moved to the doc/ directory.

Usage in TWENET

Please note the following:

We have not conducted comprehensive testing of the library’s operation.
Customers are responsible for verifying its functionality.
We also cannot provide support for questions regarding the usage of EASTL.
Please refer to the official documentation, source code, and related materials provided by the original authors.

  • The version used is EASTL 3.07 (2018/1/31),
    which is the last version compatible with C++11.
  • The following libraries are not included:
    • test/packages/EAAssert, source/assert.cpp
    • test/packages/EATest
    • test/packages/EAThread, source/thread_support.cpp
  • Test code under test/source has not been ported.
  • For sprintf related functionality, only EA::StdC::Vsnprintf(char8_t*, ...)
    is supported by calling vsnprintf_() in the printf.h library.

Integration and Compilation

EASTL can be used when writing Acts.

The necessary include paths and library additions for the TWELITE development environment are already provided.
Simply include the required library headers in the code you create.

#include <TWELITE>
#include <EASTL/fixed_string.h>

using namespace eastl;
using tstr128 = fixed_string<char, 127 + 1, false>;

void setup() {
    tstr128 s1;
    s1 = "Hello World";
    Serial << s1.c_str();
}
void loop() {
    ;
}

Detailed Integration Steps

  • Compile the code under EASTL/source into a library archive (libEASTL.a).
    Linking against this library is required during the build process.
  • Add the following include paths during compilation.

If $(PATH_EASTL) points to the EASTL directory, the include paths are as follows:

-I$(PATH_EASTL)/include
-I$(PATH_EASTL)/test/packages/EAAssert/include
-I$(PATH_EASTL)/test/packages/EABase/include/Common
-I$(PATH_EASTL)/test/packages/EAMain/include
-I$(PATH_EASTL)/test/packages/EAStdC/include
-I$(PATH_EASTL)/test/packages/EATest/include
-I$(PATH_EASTL)/test/packages/EAThread/include

Coding Guidelines

std:: vs eastl::

Both the standard library (std::) and EASTL (eastl::) define components with the same names and functionalities.
While they may sometimes be interoperable, using them together can lead to compilation errors.

As a general rule, when working with EASTL, use definitions provided by EASTL itself.
For example, attempting to store an eastl::fixed_string in a std::unique_ptr will result in a compiler error.

Global Object Initialization 1 (Placement New)

In TWENET development, due to compiler constraints, constructors for globally declared objects are not executed.
Memory for such globally declared objects is only zero-initialized.
If the code is executed as-is, it will typically hang due to null pointer access.

To properly initialize these objects, use placement new.

#include <TWELITE>
#include <EASTL/fixed_string.h>

using namespace eastl;
using tstr128 = fixed_string<char, 127 + 1, false>;

tstr128 g_str1; // constructor is NOT called! needs to be initialized before use.

void setup() {
    (void) new ((void*)&g_str1) tstr128("Hello World");
    Serial << g_str1.c_str();
}

Since the placement new code can look a bit messy, a helper function mwx::pnew() is provided. The previous example can be rewritten as follows.

(void) new ((void*)&g_str1) tstr128("Hello World");
// ↓
mwx::pnew(g_str1, "Hello World");

Note: Arguments from the second one onward are variadic and passed directly to the constructor.

Global Object Initialization 2 (unique_ptr)

As another way to initialize global objects, you can use unique_ptr (std::unique_ptr reference). Both std:: and eastl:: provide unique_ptr, but for EASTL classes, you should use the one from eastl::.

Call .reset() at the timing of initialization as shown below.

#include <TWELITE>
#include <EASTL/unique_ptr.h>
#include <EASTL/fixed_string.h>

using namespace eastl;
using tstr128 = fixed_string<char, 127 + 1, false>;

eastl::unique_ptr<tstr128> uq_str1;

void setup() {
	uq_str1.reset(new tstr128("Hello World"));
    if (uq_str1) { // true: object is stored.
        Serial << uq_str1->c_str();
    }
}

About intrusive containers

The following example shows an element definition for intrusive_list. The only member is int mX.

struct IntNode : public eastl::intrusive_list_node {
    int mX;
    IntNode(int x = 0) : mX(x) { }
        // no need to call super class's constructor eastl::intrusive_list_node()
};

inline bool operator<(const IntNode& a, const IntNode& b) { return a.mX < b.mX; }
inline bool operator>(const IntNode& a, const IntNode& b) { return a.mX > b.mX; }

Elements of intrusive_list must inherit from the intrusive_list_node base class. The base class contains link pointers used to maintain the list. Here we also define comparison operators used by functions such as sort.

using tiList = intrusive_list<IntNode>;

void setup() {
    IntNode nodeA(5);
    IntNode nodeB(1);
    IntNode nodeC(9);
    IntNode nodeD(2);
    IntNode nodeE(4);

    tiList l; // intrusive_list body

    l.push_front(nodeA); // forming list strucure
                         //   by updating link info in intrusive_list_node.
    l.push_front(nodeB);
    l.push_front(nodeC);
    l.push_front(nodeD);
    l.push_front(nodeE);

    l.sort(); // sort, using < operator
    l.sort(eastl::greater<tilist::value_type>()); // sort, using > operator
}

References

About this sample

The EASTL license description is as follows.

Modified BSD License (3-Clause BSD license) see the file LICENSE in the project root.

/*
Copyright (C) 2015 Electronic Arts Inc.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1.  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
2.  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
3.  Neither the name of Electronic Arts, Inc. ("EA") nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

The sample code applies MWSLA-1J/E.

6 - TWENETstgs - twesettings Library

A library that supports interactive mode settings
This section explains the TWENETstgs - twesettings library.

TWENETstgs - twesettings Library

This library primarily contains various functions for performing configuration processing in interactive mode.

Note: These functions are not publicly exposed as APIs for end-users.

6.1 - printf library

printf library
Explanation of printf-equivalent functions.

printf-equivalent functions

{{< hint color=“info” >}} The printf library to reference is stored in TWENETmcu/printf. {{< /hint >}}

This TWENETstgs defines fprintf, vfprintf, and sprintf equivalent functions using an open-source printf library.

int TWE_fprintf(TWE_tsFILE *fp, const char *format, ...);
int TWE_vfprintf(TWE_tsFILE *fp, const char *format, va_list va);
#define TWE_snprintf(out,siz,fmt,...) snprintf_(out,siz,fmt,__VA_ARGS__)

Referenced Source Code Description

///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
//             2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
//        embedded systems with a very limited resources.
//        Use this instead of bloated standard/newlib printf.
//        These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////

6.2 - TWESTG_CMD_u32CmdOp() Command Explanation

TWESTG_CMD_u32CmdOp() Command Explanation (for internal developers)
This section explains the commands for TWESTG_CMD_u32CmdOp().

TWESTG_CMD_u32CmdOp() Command Explanation (for Internal Developers)

Overview

The TWESTG_CMD_u32CmdOp() function in twesettings_cmd.[ch] is intended to execute 0xdb commands. This function includes processes such as obtaining module various information, obtaining configuration information, reflecting configuration information, and resetting. Many processes call the configuration-related helper function TWEINTRCT_cbu32GenericHandler().

Data Types

  • TWE_APIRET: Success if the 0x80000000 bit is set, failure if not. The remaining 31 bits are used for parameters.
  • TWE_tsBuffer: A structure containing a pointer to the buffer, the sequence length, and the maximum buffer length.
  • TWESTG_tsFinal: The management structure for configuration-related settings.

TWESTG_CMD_u32CmdOp()

TWE_APIRET TWESTG_CMD_u32CmdOp(uint8 u8Op, TWE_tsBuffer *pBufIn, TWE_tsBuffer *pBufOut, TWESTG_tsFinal *psFinal)

Performs processing corresponding to u8Op. Input data pBufIn and output data pBufOut are used depending on the process. The last parameter specifies the configuration management structure psFinal.

ParameterTypeDescription
u8Opuint8Specifies the processing content.
pBufInTWE_tsBuffer *Input sequence.
pBufOutTWE_tsBuffer *Specifies the storage area for output data. NULL can be specified for some processes. The state on processing failure is undefined in principle.
psFinalTWESTG_tsFinal *Specifies the configuration information management structure.

The u8Op overview is as follows:

E_TWESTG_CMD_OP_ACK = 0xF0                    ACK processing
E_TWESTG_CMD_OP_QUERY_MODULE_INFO = 0xF1    Acquisition of SID, etc.
E_TWESTG_CMD_OP_APPLY_SETTINGS = 0xF2        Apply settings (do not save)
E_TWESTG_CMD_OP_QUERY_SETTINGS = 0xF3        Read settings
E_TWESTG_CMD_OP_MODULE_CONTROL = 0xF8        Various processes related to settings
E_TWESTG_CMD_OP_REVERT = 0xFD               Revert settings
E_TWESTG_CMD_OP_SAVE = 0xFE                 Save settings
E_TWESTG_CMD_OP_DO_MDDULE_RESET = 0xFF,     Module reset

The return value indicates success or failure. Parameters may be set depending on the process.

Return ValueValueStatus
TWE_APIRET_SUCCESSb0..b7 → u8Op, others depend on processingOn success
TWE_APIRET_FAILb0..b7 → u8Op, others depend on processingOn failure

Processing

E_TWESTG_CMD_OP_ACK (F0)

Performs an ACK response. The input sequence is output as-is.

Example
(None) -> 01       : If no input, 01 is returned.
112233 -> 112233   : If 112233, it is returned as-is in the output.

E_TWESTG_CMD_OP_QUERY_MODULE_INFO (F1)

Retrieves various module information.

Input ColumnData TypeValueContent
[0]OCTET0x01Get module’s SID.
OtherUndefined
Subsequent data is undefined
Output Column ([0] == 0x01)Data TypeValueContent
[0..3]BE_DWORDModule’s SID.

E_TWESTG_CMD_OP_APPLY_SETTINGS(F2)

Modifies configuration information.

  • Configuration information will not be applied until it is saved and the module is reset.
  • The behavior of the application in an unapplied state is undefined.
  • If you transition to interactive mode in an undefined state, the changed data will be discarded.
  • Even when attempting to change to the same content as existing data, this process returns a successful return value. However, if a save (E_TWESTG_CMD_OP_SAVE) is executed, no actual save will occur.
  • This process does not write to the output (pBufOut).
Input ColumnData TypeValueContent
[0]OCTET0x01Change the setting specified by ID.
[1]OCTETNot 0x00Setting ID
[2..]Data type dependent
Configuration Data
Setting IDContentInput DataRemarks
0x01Application IDBE_DWORD (uint32_t)
0x02Logical ID (8bit)OCTET (uint8_t)
0x03ChannelOCTET (uint8_t)
0x04Multiple ChannelsBE_WORD(uint16_t)b0: ch11, b1: ch12, …, b15: ch16
BE_DWORD(uint32_t)Bitwise OR of 1UL << ch (e.g., for 11, 13 it’s `1UL « 11
0x05Radio Output and RetransmissionOCTET (uint8_t)Upper 4 bits: retransmission count, Lower 4 bits: output setting (0..3, 3 is highest output)
0x06, 0x08, 0x09, 0x0AOption (32bit)BE_DWORD (uint32_t)
0x07UART SettingsBE_WORD (int16_t)Input configuration data in internal format as-is.
BE_DWORDSpecifies baud rate (9600 … 250000). Other communication conditions are 8N1.
BE_DWORD OCTET OCTET OCTETSpecifies all parameters:
- Baud rate (DWORD)
- Data bits (7 or 8)
- Parity (‘N’ or ‘E’ or ‘O’)
- Stop bits (1 or 2)
Example
01011234BEEF        Sets Application ID (0x01) to 0x1234BEEF.
010212              Sets Channel (0x02) to 0x12 (18).

E_TWESTG_CMD_OP_QUERY_SETTINGS(F3)

Retrieves configuration information.

Input ColumnData TypeValueContent
[0]OCTET0x01(QTYP) Get the setting specified by ID.
[1]OCTETNot 0x00Setting ID
Output for QTYP==1
Remarks
[0]OCTETData type (uint8_t: 1, int8_t: 2, uint16_t: 3, int16_t: 4, uint32_t: 5, int32_t: 6, uint8_t[]: 0x80 (lower 5 bits are data length))
[...]Data type dependent (Integer types WORD, DWORD are Big Endian order)
Setting IDContentInput DataRemarks
0x01Application IDBE_DWORD (uint32_t)
0x02Logical ID (8bit)OCTET (uint8_t)
0x03ChannelOCTET (uint8_t)
0x04Multiple ChannelsBE_WORD(uint16_t)b0: ch11, b1: ch12, …, b15: ch16
0x05Radio Output and RetransmissionOCTET (uint8_t)Upper 4 bits: retransmission count, Lower 4 bits: output setting (0..3, 3 is highest output)
0x06, 0x08, 0x09, 0x0AOption (32bit)BE_DWORD (uint32_t)
0x07UART SettingsBE_WORD (int16_t)Internal format configuration data.
b15: 1 for 7bit, 0 for 8bit.
b14: 1 for STOPBIT=2, 0 for 1.
b12,13: 0->NONE, 1->ODD, 2->EVEN.
b0..b11->Baud rate / 100.
Example
0101 -> 051234BEEF  -> Application ID (uint32_t 0x1234beef)
0102 -> 010D        -> Channel (uint8_t 13)

E_TWESTG_CMD_OP_REVERT (0xFD)

By executing E_TWESTG_CMD_OP_SAVE immediately after this command, the configuration information is reverted to its initial values.

  • Calls TWEINTRCT_cbu32GenericHandler(psIntr, E_TWEINRCT_OP_REVERT, TRUE, 0, NULL). The TRUE specified in the third argument means that the saved configuration information is not loaded. Ensure that the application’s TWEINTRCT_cbu32GenericHandler() is correctly implemented.

No input data, no output data.

E_TWESTG_CMD_OP_SAVE (0xFE)

When configuration information is changed, it is saved to non-volatile memory.

  • If attempting to overwrite or change to the same values that are already set, no save is performed. The function returns TWE_APIRET_SUCCESS_W_VALUE(0x100 | E_TWESTG_CMD_OP_SAVE).
  • If a save is performed, a reset should be carried out promptly (operation with changed settings without reset is undefined).

No input data, no output data.

E_TWESTG_CMD_OP_DO_MDDULE_RESET (0xFF)

Resets the module.

No input data, no output data.