Skip to content

AudioMoth Library

Alex Rogers edited this page Apr 15, 2022 · 38 revisions

The AudioMoth library is defined in audioMoth.h. The library defines a number of constants and enumerations, and a large number of function prototypes that allow complete control of the AudioMoth hardware.

Definitions

All applications should maintain a firmware version (e.g. 1.0.0) and a firmware description (e.g. AudioMoth-Firmware-Basic) which can be accessed through the desktop tools. The number of bytes used to store and transfer these are defined here.

#define AM_FIRMWARE_VERSION_LENGTH             3
#define AM_FIRMWARE_DESCRIPTION_LENGTH         32

AudioMoth incorporates a 256KB external SRAM chip, connected to the Wonder Gecko micro-controller through its External Bus Interface (EBI). This external memory is mapped to a specific location in the Wonder Gecko address space and can accessed directly from within the application C code.

#define AM_EXTERNAL_SRAM_START_ADDRESS         0x80000000
#define AM_EXTERNAL_SRAM_SIZE_IN_BYTES         (256 * 1024)

The back-up domain of the Wonder Gecko supports 512 bytes of SRAM which are persistent across power-down. The AudioMoth reserves 32 of these for internal use, and the rest are free for applications to use.

#define AM_BACKUP_DOMAIN_START_ADDRESS         0x40081120
#define AM_BACKUP_DOMAIN_SIZE_IN_REGISTERS     120
#define AM_BACKUP_DOMAIN_SIZE_IN_BYTES         480

The AudioMoth flash has a spare user page that can be used for persistent data storage.

#define AM_FLASH_USER_DATA_ADDRESS             0xFE00000
#define AM_FLASH_USER_SIZE_IN_BYTES            2024

Each AudioMoth has a unique ID that is mapped to an 8-byte memory location and can be used by applications to uniquely identify devices.

#define AM_UNIQUE_ID_START_ADDRESS             0xFE081F0
#define AM_UNIQUE_ID_SIZE_IN_BYTES             8

Two battery measurement enumerations are exposed to the application. These constants enable the actual voltage in millivolts to be calculated from the enumeration.

#define AM_BATTERY_STATE_OFFSET                3500
#define AM_EXT_BAT_STATE_OFFSET                2400
#define AM_BATTERY_STATE_INCREMENT             100

Enumerations

The AudioMoth library defines a number of enumerations that are used by subsequent functions to query and set the state of the device.

typedef enum {AM_LOW_GAIN_RANGE, AM_NORMAL_GAIN_RANGE} AM_gainRange_t;

typedef enum {AM_SD_CARD_NORMAL_SPEED, AM_SD_CARD_HIGH_SPEED} AM_sdCardSpeed_t;

typedef enum {AM_HF_CLK_DIV1, AM_HF_CLK_DIV2, AM_HF_CLK_DIV4} AM_highFrequencyClockDivider_t;

typedef enum {AM_SWITCH_CUSTOM, AM_SWITCH_DEFAULT, AM_SWITCH_USB, AM_SWITCH_NONE} AM_switchPosition_t;

typedef enum {AM_HFRCO_1MHZ, AM_HFRCO_7MHZ, AM_HFRCO_11MHZ, AM_HFRCO_14MHZ, AM_HFRCO_21MHZ, AM_HFRCO_28MHZ, AM_HFXO} AM_clockFrequency_t;

typedef enum {AM_BATTERY_LOW, AM_BATTERY_3V6, AM_BATTERY_3V7, AM_BATTERY_3V8, AM_BATTERY_3V9, AM_BATTERY_4V0, AM_BATTERY_4V1, AM_BATTERY_4V2, AM_BATTERY_4V3, AM_BATTERY_4V4, AM_BATTERY_4V5, AM_BATTERY_4V6, AM_BATTERY_4V7, AM_BATTERY_4V8, AM_BATTERY_4V9, AM_BATTERY_FULL } AM_batteryState_t;

typedef enum {AM_EXT_BAT_LOW, AM_EXT_BAT_2V5, AM_EXT_BAT_2V6, AM_EXT_BAT_2V7, AM_EXT_BAT_2V8, AM_EXT_BAT_2V9, AM_EXT_BAT_3V0, AM_EXT_BAT_3V1, \
              AM_EXT_BAT_3V2, AM_EXT_BAT_3V3, AM_EXT_BAT_3V4, AM_EXT_BAT_3V5, AM_EXT_BAT_3V6, AM_EXT_BAT_3V7, AM_EXT_BAT_3V8, AM_EXT_BAT_3V9, \
              AM_EXT_BAT_4V0, AM_EXT_BAT_4V1, AM_EXT_BAT_4V2, AM_EXT_BAT_4V3, AM_EXT_BAT_4V4, AM_EXT_BAT_4V5, AM_EXT_BAT_4V6, AM_EXT_BAT_4V7, \
              AM_EXT_BAT_4V8, AM_EXT_BAT_4V9, AM_EXT_BAT_FULL} AM_extendedBatteryState_t;

Timezone hander

AudioMoth applications can provide a time zone to ensure that the timestamps in the file system are in the appropriate local time.

extern void AudioMoth_timezoneRequested(int8_t *timezoneHours, int8_t *timezoneMinutes);

Interrupt Handlers

AudioMoth applications are required to handle a number of interrupts. The simplest of these is an interrupt that triggers whenever the switch position is changed.

extern void AudioMoth_handleSwitchInterrupt(void);

Another is an interrupt that triggers whenever an external microphone is plugged or unplugged from the device.

extern void AudioMoth_handleMicrophoneChangeInterrupt(void);

Depending on how the microphone is configured the AudioMoth application may need to handle interrupts on the completion of each microphone ADC conversion.

extern void AudioMoth_handleMicrophoneInterrupt(int16_t sample);

Alternatively, AudioMoth can be configured to transfer microphone samples directly to memory under direct memory access (DMA). An interrupt is triggered each time either the primary or secondary buffer is filled. The default operation mode is a ping-pong buffer, in which case the interrupt does not have to set nextBuffer. However, if other buffer configurations are required, nextBuffer should be set to the start address of the next buffer to fill.

extern void AudioMoth_handleDirectMemoryAccessInterrupt(bool isPrimaryBuffer, int16_t **nextBuffer);

USB Message Handlers

The AudioMoth library automatically handles a number of USB messages. These include setting the time, requesting the time, requesting the battery state, and requesting the unique ID of the device. Applications can define their own USB message formats in addition to these and must handle the following four requests.

extern void AudioMoth_usbFirmwareVersionRequested(uint8_t **firmwareVersionPtr);

extern void AudioMoth_usbFirmwareDescriptionRequested(uint8_t **firmwareDescriptionPtr);

extern void AudioMoth_usbApplicationPacketRequested(uint32_t messageType, uint8_t *transmitBuffer, uint32_t size);

extern void AudioMoth_usbApplicationPacketReceived(uint32_t messageType, uint8_t *receiveBuffer, uint8_t *transmitBuffer, uint32_t size);

USB Device Initialisation

The first thing that AudioMoth applications should do is call AudioMoth_initialise to set up the hardware and configure the clocks.

void AudioMoth_initialise(void);

To reduce energy consumption, it is common for AudioMoth applications to use the real time clock to enter a power-down state between activities. Applications can use AudioMoth_isInitialPowerUp to determine whether the device has just powered up from one of these power-down periods, or from an external reset (due to initially fitting batteries or a watchdog reset).

bool AudioMoth_isInitialPowerUp(void);

Clock control

AudioMoth can use a range of different clock sources. The most accurate is the external 48MHz crystal that can be enabled, selected or disabled, using the functions below. This is enabled and selected automatically by the AudioMoth_initialise function.

void AudioMoth_enableHFXO(void);

void AudioMoth_selectHFXO(void);

void AudioMoth_disableHFXO(void);

AudioMoth also supports an internal RC oscillator which can be operated in six different frequency bands. These are enabled, selected and disabled, using the functions below. Note that when changing clock source, it is necessary to select the new clock source, before disabling the existing one.

void AudioMoth_enableHFRCO(AM_clockFrequency_t frequency);

void AudioMoth_selectHFRCO(void);

void AudioMoth_disableHFRCO(void);

The frequency of any particular HFRC frequency band can be retrieved using the AudioMoth_getClockFrequency function.

uint32_t AudioMoth_getClockFrequency(AM_clockFrequency_t frequency);

External SRAM Control

The external SRAM may not be necessary in all applications and is disabled and powered down by default. It may be enabled and then disabled as required.

void AudioMoth_enableExternalSRAM(void);

void AudioMoth_disableExternalSRAM(void);

Microphone samples

The microphone of the AudioMoth is powered up and enabled using the function below. This function requires the gain range and gain setting to be specified, the divider that is applied to the main clock to generate the ADC clock, the number of acquisition cycles over which the ADC collects data, and the hardware oversampling rate. It returns a Boolean indicating whether or not an external microphone is being used.

bool AudioMoth_enableMicrophone(AM_gainRange_t gainRain, uint32_t gain, uint32_t clockDivider, uint32_t acquisitionCycles, uint32_t oversampleRate);

The transfer of microphone samples can then be configured to use either direct interrupts on the completion of each ADC conversion, or using direct memory transfer to transfer a number of samples into memory. The latter uses ping-pong buffering by default and is initialised with pointers to the primary and secondary buffers, and the number of samples in each transfer (maximum 1024).

void AudioMoth_initialiseMicrophoneInterupts(void);

void AudioMoth_initialiseDirectMemoryAccess(int16_t *primaryBuffer, int16_t *secondaryBuffer, uint16_t numberOfSamples);

The actual collection of microphone samples is started with the function below which uses a timer to generate samples at the specified sample rate.

void AudioMoth_startMicrophoneSamples(uint32_t sampleRate);

Finally, the microphone can be disabled and powered down using the function below.

void AudioMoth_disableMicrophone(void);

USB

The AudioMoth_handleUSB functions handles all communication with the host computer. The AudioMoth library automatically handles requests to set the time, read the time, read the battery state, and read the unique ID of the device. If the AudioMoth device is not connected to a USB host, it will enter a low-power state until it is reconnected. Function will return immediately if the switch is not in the 'USB' and will block until the switch moved away from 'USB'

void AudioMoth_handleUSB(void);

Backup Domain

AudioMoth provides an area of internal SRAM which is persistent across device power down. This can be accessed directly through the AM_EXTERNAL_SRAM_START_ADDRESS address, or through the two functions below.

uint32_t AudioMoth_retreiveFromBackupDomain(uint32_t register);

void AudioMoth_storeInBackupDomain(uint32_t register, uint32_t value);

Flash User Data Page

The EFM32WG processor includes a flash page for user data. This function allows applications to write to this page.

bool AudioMoth_writeToFlashUserDataPage(uint8_t *data, uint32_t length);

Time

AudioMoth has a real-time counter that can be set and read through the methods below. The real-time counter continues to run when the device is in powered down. A flag indicates whether the time has been set since the last device reset.

bool AudioMoth_hasTimeBeenSet(void);

void AudioMoth_setTime(uint32_t time, uint32_t milliseconds);

void AudioMoth_getTime(uint32_t *time, uint32_t *milliseconds);

Watch Dog Timer

AudioMoth automatically runs a watch dog timer to prevent software hanging. If the watch dog timer is not fed every 60 seconds it will reset the device. In normal operation, when collecting microphone samples or interacting with USB, the AudioMoth library automatically feeds the watch dog timer. If the user application performs a very long operation it may be necessary to temporarily disable the watch dog timer or to feed it manually.

void AudioMoth_startWatchdog(void);

void AudioMoth_stopWatchdog(void);

void AudioMoth_feedWatchdog(void);

bool AudioMoth_hasWatchdogResetOccured(void);

Real Time Clock

In normal operation, the watchdog timer is automatically reset by operations such as microphone sample interrupts. When long-duration activities are required (such as waiting in deep sleep after a USB cable has been unplugged) it is necessary to generate additional interrupts that automatically feed the watchdog timer, and to check for time overflow immediately after the interrupt. These functions allow for this process. The range of these arguments are 1 to 60 seconds, and 1 to 1000 milliseconds.

void AudioMoth_startRealTimeClock(uint32_t seconds);

void AudioMoth_startRealTimeClockMilliseconds(uint32_t milliseconds);

void AudioMoth_stopRealTimeClock(void);

void AudioMoth_checkAndHandleTimeOverflow(void);

Supply Voltage State Monitoring

The supply voltage to the AudioMoth processor can be accessed using the functions below.

void AudioMoth_enableSupplyMonitor(void);

void AudioMoth_disableSupplyMonitor(void);

void AudioMoth_setBatteryMonitorThreshold(uint32_t batteryVoltage, uint32_t supplyVoltage);

bool AudioMoth_isSupplyAboveThreshold(void);

Battery State Monitoring

The state of the AudioMoth battery can be accessed using the functions below.

void AudioMoth_enableBatteryMonitor(void);

void AudioMoth_disableBatteryMonitor(void);

void AudioMoth_setBatteryMonitorThreshold(AM_batteryState_t batteryState);

bool AudioMoth_isBatteryMonitorAboveThreshold(void);

Supply and Battery Reporting

The supply voltage and battery state can be reported using the functions below.

uint32_t AudioMoth_getSupplyVoltage(void);

AM_batteryState_t AudioMoth_getBatteryState(uint32_t supplyVoltage);

AM_extendedBatteryState_t AudioMoth_getExtendedBatteryState(uint32_t supplyVoltage);

Temperature Monitoring

The temperature of the AudioMoth processor can be accessed with the functions below.

void AudioMoth_enableTemperature(void);

void AudioMoth_disableTemperature(void);

int32_t AudioMoth_getTemperature(void);

Switch Position Monitoring

The current state of the AudioMoth switch can be accessed using the function below.

AM_switchPosition_t AudioMoth_getSwitchPosition();

Delay

The function below uses a timer to give a precise time interval. The AudioMoth is in a low-power sleep mode while waiting for the required duration.

void AudioMoth_delay(uint32_t milliseconds);

Sleep and Power Down

To ensure minimum power consumption it is common to sleep the AudioMoth device whilst waiting for microphone samples to be available. This is achieved through a single function that puts the device into EM1.

void AudioMoth_sleep();

A deeper sleep state is available (EM2) through another call.

void AudioMoth_deepSleep();

The device may also be powered down. This is permanent and requires the cycling of the power (removing and refitting batteries) to wake again.

void AudioMoth_powerDown();

More useful is the ability to power down and automatically wake up after a number of seconds. This function uses the real-time counter and ensures that the power down energy consumption is in the order of 20 - 30 uA. There are two versions of this function: one that powers down for a set number of milliseconds, and another measures time in seconds and uses a synchronised flag to indicate whether the next wake-up should occur on the transition of the second counter, or if the device should be powered down for the full seconds seconds.

void AudioMoth_powerDownAndWakeMilliseconds(uint32_t millisecond);

void AudioMoth_powerDownAndWake(uint32_t seconds, bool synchronised);

LED Control

The red and green LED can be controlled using the functions below.

void AudioMoth_setRedLED(bool state);

void AudioMoth_setBothLED(bool state);

void AudioMoth_setGreenLED(bool state);

File System

AudioMoth supports writing of any file type to the microSD card. The file system in enabled and disabled (including powering up and powering down the microSD card) with the two functions below. The enable function takes an argument indicating the SD card speed. The normal speed uses a 12 MHz SPI clock rate, and the high speed option doubles this to 24 MHz. The standard firmware uses high speed for samples rates of 250 and 384 kHz, and normal speed otherwise.

bool AudioMoth_enableFileSystem(AM_sdCardSpeed_t speed);

void AudioMoth_disableFileSystem();

The library allows the existance of a file to be checked.

bool AudioMoth_doesFileExist(char *filename);

The library allows a new file to be opened (overwriting an existing file or to read) and an existing file to be appended.

bool AudioMoth_openFile(char *filename);

bool AudioMoth_openFileToRead(char *filename);

bool AudioMoth_appendFile(char *filename);

It is also possible to move to any point within the file.

bool AudioMoth_seekInFile(uint32_t position);

Files are written using the function below.

bool AudioMoth_writeToFile(void *bytes, uint16_t bytesToWrite);

File can be read using the function below.

bool AudioMoth_readFile(char *buffer, uint32_t bufferSize);

If the file is not immediately closed, subsequent writes are buffered to ensure that the microSD card is written to in blocks of 512 bytes. Updating files with multiple small changes (closing the file each time) is inefficient as the microSD card can typically only update 512 byte pages and thus must repeatedly read and write to the same page.

bool AudioMoth_closeFile();

Existing closed files can also be renamed.

bool AudioMoth_renameFile(char *originalFilename, char *newFilename);

It is also possible to flush the file buffer, and to update the file size in the file allocation table, whilst leaving the file open for further writes. See here for more details of this functionality.

bool AudioMoth_syncFile(void);

The library also allows the existence of directories to be tested, new directories to be created and files placed in those directory using '/' as the file path separator.

bool AudioMoth_doesDirectoryExist(char *folderName);

bool AudioMoth_makeDirectory(char *folderName);

Debugging System

If using AudioMoth connected to an external debugger, serial standard output can be enabled.

void AudioMoth_setupSWOForPrint(void);