BOS1901 Oscillator Trimming

BOS1901 contains an internal oscillator for time-based operations such as driving the output using FIFO data at a given sampling rate. This oscillator is factory-trimmed for accurate operation. There are cases however where its software-trimming feature become useful. One example is synchronizing the BOS1901 with a microcontroller (MCU) for real-time sampling such as continuously streaming content.

This document describes how to perform this trimming at runtime using the BOS1901 SPI interface and register map structure. This trimming is used in the application note Driving Piezoelectric Actuator using BOS1901 and its associated code examples.

1 Reading a Register

Trimming the BOS1901 internal oscillator requires reading some register content. This is done in three steps:

  1. Setting which register to broadcast on the SPI interface.
  2. Sending another word on the SPI interface.
  3. Reading the register content received on the SPI interface during step 2.

To set which register will be broadcast, the BC parameter in the CONFIG register must be set to the value of this register. For example, to read the TRIM_OSC parameter, BC must be set to 0xE, the address of the TRIM register.

Once BOS1901 has been configured to broadcast the desired register, this register is read by writing any word on the SPI interface and reading SDO at the same time. Be careful to write a word that will not change the configuration or state of the IC unless intended. For example, write the same word again, or write to a read-only register.

It is possible to set the next register to be read while reading the currently set register broadcast. For example, the following sequence is possible:

  1. Set BC = 0x1 address. This sets register 0x1 to be read.
  2. Write CONFIG with BC = 0x2 address and read SDO at the same time. This reads register 0x1 while setting subsequent broadcasts to 0x2.
  3. Write CONFIG with BC = 0x3 address and read SDO at the same time. This reads register 0x2 while setting subsequent broadcasts to 0x3. And so on.

2 Trim Control

BOS1901 trim control is depicted in the following figure. BOS1901 uses values stored in the trim block to trim the internal oscillator and the regulator. By default, factory-trimmed hardware fuses are selected and their value is loaded into the trim block. It is possible however to send trimming value to the TRIM register (0xE) and send these values to the trim block, thereby dynamically changing the oscillator trimming value.

When reading the oscillator trimming value, the returned value is the one stored in the trim register. By default, the trim block content is not sent to the TRIM register for reading, therefore this register will read 0xE000 initially. An explicit operation is required to send the trim block content to the TRIM register. It follows that in order to read the hardware fuses value, it must first be loaded from the trim block into the trim register.

When a soft reset is done (RST = 1 in CONFIG register – 0x5), the TRIM register contents defaults back 0xE000 but the trim block maintains its value.

Note that trimming values for the regulator are also coming from the same trim block. When trimming the oscillator, care must be taken to maintain the regulator trimming value coming from the hardware fuses.

Figure 1 Block diagram: trim control

The TRIM register contains the following parameters:

TRIMRW: this parameter defines the behavior of the trim control block.

  • 0x0: does nothing. By default, latching hardware fuses to trim block at power up. Upon soft reset, trim block keeps the same values a previously.
  • 0x1: latches hardware fuses to the trim block and makes this data available in the TRIM register for reading.
  • 0x2: allows the trim value from the trim block to be read in the TRIM register.
  • 0x3: writes the software trim value to the TRIM register and latches this register to the trim block.

SDOBP: assigns the internal clock signal to the SDO pin. It is seldom used in operation.

TRIM_OSC: the internal oscillator 6 trim bits in 2’s complement. The trimming resolution is about 150 kHz. The oscillator typical frequency is 14.3 MHz.

TRIM_REG: the internal regulator 3 trim bits in 2’s complement.

Writing to the TRIM register writes to all four parameters. SDOBP will stay at 0x0 in almost all cases. However, writing to TRIM_OSC also writes to TRIM_REG. It is therefore required to read the hardware fuses values for those parameters before making modifications so TRIM_REG may be rewritten the same value when changing TRIM_OSC value.

Note that output must be disabled (OE = 0) for trimming to occur or to read the TRIM register. Otherwise, the operation will be ignored. It is not possible to change the trim settings while the IC is driving or sensing.

3 Reading Hardware-Trimmed Value

To read the hardware fuses trim value, follow these steps.

  1. Set TRIM register to hardware fuses and to make this data available (TRIMRW = 0x1). Other parameters may be kept to 0x0, they are ignored in this operation. Thus, write 0xE400 on SPI.
  2. Write CONFIG register (0x5) to set SDO pin broadcast to read the TRIM register (BC = 0xE).
  3. Write CONFIG register again in order to read the TRIM register value.

TRIM_OSC and TRIM_REG can be extracted from the read register.

4 Reading Previously Trimmed Value

To read the previously trimmed value, follow these steps.

  1. Set TRIM register to read the trim value from the trim block and to make this data available (TRIMRW = 0x2). Other parameters may be kept to 0x0, they are ignored in this operation. Thus, write 0xE800 on SPI.
  2. Write CONFIG register (0x5) to set SDO pin broadcast to read the TRIM register (BC = 0xE).
  3. Write CONFIG register again in order to read the TRIM register value.

TRIM_OSC and TRIM_REG can be extracted from the read register.

5 Writing a Trim Value

To change the oscillator trim value (TRIM_OSC) in the TRIM register, follow these steps.

  1. Read the content of the TRIM register, either using the hardware fuses or the previously trimmed value, using the methods given in the previous sections.
  2. Change the value of TRIMRW in the register to 0x3 to write the new software trim value.
  3. Change the TRIM_OSC in the register to the new software trim value for the oscillator. Either replace its value by the appropriate trim value or increment it by the appropriate amount.
  4. Write the resulting register word (16 bits) on the SPI interface.

In steps 2 and 3, make sure to not modify the other register parameters (SDOBP and TRIM_REG). This may be done using bitwise operations or unions in the source code. See the code examples that showcase bitwise operations. See the BOS1901-KIT development platform source code for unions example code.


6 Trimming Sampling Rate to a Specific Value

When the amount of trimming required is known, it is possible to directly trim the oscillator to the appropriate value using the equation below. FIFO sampling rate is based on the internal 14.3 MHz oscillator. Its trimming resolution is approximately 150 kHz.

Where, Δ𝑇𝑟𝑖𝑚 is the trimming increment in LSBs,
𝑓𝑆 is the sampling rate frequency,
Δ𝑓𝑆 is the sampling rate change to apply,
𝑓𝑜𝑠𝑐 is the internal oscillator frequency (14.3 MHz),
Δ𝑓𝑜𝑠𝑐 is the oscillator trimming step (150 kHz).
For example, to trim the 8 kHz sampling rate by +2 %

7 Synchronizing BOS1901 with MCU (Direct Sampling)


When a sampling rate is imposed by the MCU by regularly sending the samples over SPI, the BOS1901 needs to be able to play those points as they are sent. Otherwise, when playing long waveforms, data may accumulate in the FIFO. If the FIFO eventually fills up, new points will be lost, and distortion will appear in the output voltage waveform.

The solution is to trim the BOS1901 internal oscillator slightly faster than the factory-trimmed value in order to have it play points slightly faster than the SPI data transfer cadenced by the MCU – the BOS1901 is operated in direct sampling. The principle is to have the MCU send dummy data (0x0000) to the BOS1901 internal FIFO at a rate slightly higher than the one intended (about 2.5 %). For example, to drive the BOS1901 at 8 kSPS, set the MCU data rate at 8.2 kSPS.

Query the BOS1901 to check if the FIFO is accumulating data. If it does, trim it up one increment. Then repeat this process until the FIFO does not accumulate any point over a significant amount of time. For example, a 10000-cycle test will take 1-2 ms to complete.

This process of trimming the oscillator takes into account both the BOS1901 internal oscillator and the MCU internal oscillator accuracies at the same time. It is useful when streaming waveforms, either because they are generated on the fly by signal processing in the MCU or when they are driven by the system (USB audio or other). This is the method used for audio streaming in BOS1901-KIT firmware.

8 Synchronizing Two BOS1901


BOS1901 does not have a synchronization feature. Since they likely have different oscillator accuracy, the same principle can be applied to drive two BOS1901 with the same signal. Otherwise, using a FIFO-based method, waveforms may phase-shift significantly over time.

To drive two BOS1901 with the same signal, both drivers need to be trimmed using the method described in the previous section. Then the MCU can send the same data, at the same rate, to both drivers. It follows that both drivers will keep their FIFO empty at all times, and each new point will be played at the same time on each output, thereby producing synchronized waveforms.

9 Code Example

Code examples can be found on the Boréas Technologies website in the technical documents section, under BOS1901-KIT Firmware. Look for the driving example, contained in driving.c.
The example follows the sensing phases explained in the application note Sensing Piezoelectric Actuator Force using BOS1901. Pressing the actuator generate simulated click-button behavior. However, the feedback is generated using a timer-based (direct sampling) playback method.
Take a closer look at these functions:

  • driving.c
    • drivingInit: initialization instructions for sensing and driving. Calls drivingTrimming early in the execution to perform the initial trimming.
    • drivingTrimming: main oscillator trimming function, determines if TRIM_OSC need to be changed.
    • drivingSoftwareTrimming: trimming utility function, retrieves TRIM_OSC value and increases it.

10 Related Parts

Part Number Description
1 BOS1901 BOS1901 Piezo Haptic Driver with Digital Front End