Getting Started
This guide walks through adding the nPZero Driver API to your project and performing a first configuration of the IC.
1. Add the Driver Files
Copy all files from Inc/ and Src/ into your project:
your_project/
├── Inc/
│ ├── npz.h
│ ├── npz_hal.h
│ ├── npz_device_control.h
│ ├── npz_logs.h
│ └── npz_registers.h
└── Src/
├── npz.c
├── npz_hal.c ← adapt this to your platform
├── npz_device_control.c
└── npz_logs.c
2. Adapt the HAL
Open Src/npz_hal.c and replace the STM32L0 HAL calls with the I2C API for your target MCU. See Platform Porting for details.
The three functions you must implement are:
| Function | Purpose |
|---|---|
npz_hal_init() | Initialise the MCU I²C peripheral |
npz_hal_read() | Blocking I²C register read |
npz_hal_write() | Blocking I²C register write |
3. Define Your Configuration
Include the high-level header in your main.c:
#include "npz_device_control.h"
#include "npz_logs.h"
ADC Channel Config
Both ADC channel structs must be populated, even if you do not use the ADC. Pass wakeup_enable = 0 and non-zero thresholds to disable wake.
npz_adc_config_channels_s adc_internal = {
.over_threshold = 0x30, // ~2.6 V on VBAT
.under_threshold = 0x24, // ~1.5 V on VBAT
.wakeup_enable = 1,
};
npz_adc_config_channels_s adc_external = {
.over_threshold = 0x1F, // ~1.2 V on ADC_IN
.under_threshold = 0x08, // ~0.7 V on ADC_IN
.wakeup_enable = 0, // disabled
};
Peripheral Config (I²C example)
// Init sequence for an I2C temperature sensor (e.g. TMP116)
static uint8_t temp_init_bytes[] = {
0x01, 0x22, // write register 0x01, value 0x22
};
npz_peripheral_config_s periph1 = {
.communication_protocol = COM_I2C,
.power_mode = POWER_MODE_PERIODIC,
.polling_mode = POLLING_MODE_PERIODIC_READ_COMPARE_THRESHOLD,
.power_switch_mode = POWER_SWITCH_MODE_STANDARD,
.interrupt_pin_mode = INTERRUPT_PIN_MODE_INPUT_ACTIVE_HIGH,
.comparison_mode = COMPARISON_MODE_OUTSIDE_THRESHOLD,
.sensor_data_type = DATA_TYPE_INT16,
.multi_byte_transfer_enable = MULTIBYTE_TRANSFER_DISABLE,
.swap_registers = ENDIAN_BIG,
.polling_period = 3277, // ~100 s at 10 Hz system clock
.threshold_over = 0x0C80, // example: 32.00 °C
.threshold_under = 0x0000,
.time_to_wait = 5,
.pre_wait_time = PRE_WAIT_TIME_EXTEND_256,
.post_wait_time = POST_WAIT_TIME_DISABLED,
.i2c_cfg = {
.command_num = 1,
.sensor_address = 0x48,
.reg_address_value = 0x00,
.wake_on_nak = 0,
.num_of_retries_on_nak = 2,
.bytes_from_sram = { 0x01, 0x22 },
},
};
Device Config
npz_device_config_s device_config = {
// Power switch control
.power_switch_normal_mode_per1 = 0,
.power_switch_normal_mode_per2 = 0,
.power_switch_normal_mode_per3 = 0,
.power_switch_normal_mode_per4 = 0,
.host_power_mode = HOST_POWER_MODE_SWITCH,
.power_switch_gate_boost = 0,
// Wake-up sources
.wake_up_per1 = 1,
.wake_up_per2 = 0,
.wake_up_per3 = 0,
.wake_up_per4 = 0,
.wake_up_any_or_all = WAKEUP_ANY,
// Clock
.system_clock_divider = SCLK_DIV_DISABLE,
.system_clock_source = SYS_CLOCK_10HZ,
// Pin / I²C / SPI config
.io_strength = IO_STR_NORMAL,
.i2c_pull_mode = I2C_PULL_AUTO,
.spi_auto = SPI_PINS_AUTO_DISABLE,
.xo_clock_out_sel = XO_CLK_OFF,
// Global timeout (system clock periods)
.global_timeout = 3277, // ~100 s at 10 Hz
// Interrupt pin pull-ups
.interrupt_pin_pull_up_pin1 = INT_PIN_PULL_LOW,
.interrupt_pin_pull_up_pin2 = INT_PIN_PULL_DISABLED,
.interrupt_pin_pull_up_pin3 = INT_PIN_PULL_DISABLED,
.interrupt_pin_pull_up_pin4 = INT_PIN_PULL_DISABLED,
// Peripherals (NULL = disabled)
.peripherals = { &periph1, NULL, NULL, NULL },
// ADC
.adc_ext_sampling_enable = 0,
.adc_clock_sel = ADC_CLK_SC,
.adc_channels = { &adc_internal, &adc_external },
};
4. Initialize and Configure
int main(void) {
// Platform init (clocks, GPIO, etc.) — your code here
// 1. Initialise the I²C HAL
if (npz_hal_init() != OK) {
// Handle error
}
// 2. (Optional) verify the device by reading chip ID
uint8_t chip_id = 0;
npz_read_ID(&chip_id);
// Host has been woken — read status to find the cause
npz_register_sta1_s sta1 = {0};
npz_register_sta2_s sta2 = {0};
npz_read_STA1(&sta1);
npz_read_STA2(&sta2);
if (sta2.per1_triggered) {
int value = 0;
npz_device_read_peripheral_value(PSW_LP1, 0, &value);
// Process sensor value
}
if (sta1.int_adc_triggered) {
npz_device_handle_adc_internal();
}
// 3. Apply the full device configuration
npz_device_configure(&device_config);
// 4. (Optional) log settings to verify
npz_log_configurations(&device_config);
// 5. Put device into idle mode — it now operates autonomously
npz_device_go_to_idle();
while (1) {
}
}
5. Reading Wake-Up Cause
After the host wakes up, read STA1 and STA2 to determine what triggered it:
| Register | Field | Meaning |
|---|---|---|
| STA1 | reset_source | Power-on, external, or soft reset |
| STA1 | int_adc_triggered | Internal ADC (VBAT) threshold crossed |
| STA1 | ext_adc_triggered | External ADC (ADC_IN) threshold crossed |
| STA1 | global_timeout_triggered | Timeout expired before any source triggered |
| STA2 | per1_triggered … per4_triggered | Which peripheral fired |
| STA2 | per1_global_timeout … per4_global_timeout | Peripheral timed out |