Difference between revisions of "PineTime"

From PINE64
Jump to navigation Jump to search
Line 98: Line 98:
* Put the MCU to sleep as soon and as often as possible. If you are not using a RTOS, this is done by calling ''WFE'' (wait for event) instruction. Most of the time, RTOS implement this functionality. For example, FreeRTOS calls it the ''tickless mode'' : it puts the CPU in sleep mode when no task is planned for execution for more than a specified time, and wakes up as soon as an event is detected or when a task is ready to run.
* Put the MCU to sleep as soon and as often as possible. If you are not using a RTOS, this is done by calling ''WFE'' (wait for event) instruction. Most of the time, RTOS implement this functionality. For example, FreeRTOS calls it the ''tickless mode'' : it puts the CPU in sleep mode when no task is planned for execution for more than a specified time, and wakes up as soon as an event is detected or when a task is ready to run.
* Do not use logging (JLink RTT, SWO, semihosting,...), it uses a lot of power.
* Do not use logging (JLink RTT, SWO, semihosting,...), it uses a lot of power.
* Ensure that the debug circuitry of the MCU is not enabled when you measuring the battery life. The debug peripheral is enabled as soon as you connect a debugger to the device, and '''is not automatically disabled''', even if you disconnect the debugger. The software running in the NRF52832 cannot disable the debug peripheral. How to disable the debug circuitry:
* Ensure that the debug circuitry of the MCU is not enabled when you measuring the battery life. The debug peripheral is enabled as soon as you connect a debugger to the device, and '''is not automatically disabled''', even if you disconnect the debugger (unless the battery goes flat and is subsequently charged). The software running in the NRF52832 cannot disable the debug peripheral. How to disable the debug circuitry:
   - using ''nrfjprog --reset''
   - using ''nrfjprog --reset''
   - using JLinkExe : issue the command ''writeDP 1 0''
   - using JLinkExe : issue the command ''writeDP 1 0''
Line 106: Line 106:
   - issue the command ''flash fillw 0x10001208 0xFFFFFF00 0x01''
   - issue the command ''flash fillw 0x10001208 0xFFFFFF00 0x01''
   - issue the command ''reset''
   - issue the command ''reset''
  you can check if the debug port is enabled using the following code
  DWT->CYCCNT ? "NO":"YES"
* Read [https://infocenter.nordicsemi.com/pdf/nRF52832_Rev_2_Errata_v1.1.pdf the errata sheet of the MCU] and apply workarounds if they apply to your software.
* Read [https://infocenter.nordicsemi.com/pdf/nRF52832_Rev_2_Errata_v1.1.pdf the errata sheet of the MCU] and apply workarounds if they apply to your software.



Revision as of 20:40, 1 March 2020

Frequently asked questions

Read these first!

Specifications

Dimensions: 37.5 x 40 x 11mm
Weight: 38 grams
IP Rating: IP67 (waterproof to 1 meter)
Display:

Size: 1.3 inches (33mm) diagonal
Type: IPS capacitive touchscreen, RGB 65K colors
Display Controller: ST7789
Resolution: 240x240 pixels

System on Chip: Nordic Semiconductor nRF52832
Flash: 512KB with additional 4MB SPI NOR
RAM: 64KB
Bluetooth: 5.0 (including Bluetooth Low Energy)
Sensors: Accelerometer, Heart rate sensor
Feedback: Vibration motor
Battery: 170-180mAh LiPo

SWD Pinout

The devkits have exposed SWD pins for flashing and debugging. The pinout is: PineTime SWD location.jpg

Driving the peripherals

Display

Note: The factory-default software on the PineTime does not auto-detect the display being disconnected when it has already booted. That can cause garbled output, to fix it just restart the PineTime.

The display is driven using the ST7789 display controller. Use the following pins to drive the screen:

PineTime pin ST7789 pin
LCD_SCK (P0.02) SPI clock
LCD_SDI (P0.03) SPI MOSI
LCD_RS (P0.18) Clock/data pin (CD)
LCD_CS (P0.25) Chip select
LCD_RESET (P0.26) Display reset
LCD_BACKLIGHT_{LOW,MID,HIGH} Backlight (active low)

Notes:

  • Chip select must be held low while driving the display. It must be high when using other SPI devices on the same bus (such as external flash storage) so that the display controller won't respond to the wrong commands.
  • SPI must be used in mode 3. Mode 0 (the default) won't work.
  • LCD_DISPLAY_* is used to enable the backlight. Set at least one to low to see anything on the screen.
  • Use SPI at 8MHz (the fastest clock available on the nRF52832) because otherwise refreshing will be super slow.

References:

Adafruit ST7789 driver in cpp

Battery measurement

Reading whether the PineTime has power attached is easy: simply read the charge indication pin (P0.12). When it is high it is running on battery, when it is low it is charging.

Reading the battery voltage is a bit harder. For that you can use the battery voltage pin on P0.31 (AIN7). The returned value is 12 bits, which means it is 0..4095. You can get the measured voltage with the following formula, assuming a reference voltage of 3.3V (this is configurable in the ADC):

adcVoltage = adcValue / (4095 / 3.3)

The measured voltage is actually half of the actual battery voltage, because the ADC is connected between a voltage divider where both resistors are 1MΩ. This can be corrected by multiplying the value:

batteryVoltage = adcValue * 2 / (4095 / 3.3)

It's often better to avoid floating point values on embedded systems and in this case there is no reason to use float at all, we can just represent the value in millivolts. Therefore the formula can be simplified to:

batteryVoltage = adcValue * 2000 / (4095 / 3.3)
batteryVoltage = adcValue * 2000 / 1241

Converting this voltage to an estimated capacity in percent requires a more complicated algorithm, because Lithium-ion batteries have a non-linear discharge curve.

How to write battery friendly software?

The key to save battery is to enable only what you need when you need it. NRF52832 has a lot of functionalities allowing you to draw as little current as possible. Here are some tips and tricks:

  • Disable / shutdown / put in sleep mode all devices around the MCU (display controller, touch controller, external memory,...).
  • Disable all peripheral inside the MCU when you don't need them (SPI, TWI(I²C),...). The power management of the NRF52832 is very smart and will completely shut down (power off and disable the clock) the peripheral when the software disables it.
  • Put the MCU to sleep as soon and as often as possible. If you are not using a RTOS, this is done by calling WFE (wait for event) instruction. Most of the time, RTOS implement this functionality. For example, FreeRTOS calls it the tickless mode : it puts the CPU in sleep mode when no task is planned for execution for more than a specified time, and wakes up as soon as an event is detected or when a task is ready to run.
  • Do not use logging (JLink RTT, SWO, semihosting,...), it uses a lot of power.
  • Ensure that the debug circuitry of the MCU is not enabled when you measuring the battery life. The debug peripheral is enabled as soon as you connect a debugger to the device, and is not automatically disabled, even if you disconnect the debugger (unless the battery goes flat and is subsequently charged). The software running in the NRF52832 cannot disable the debug peripheral. How to disable the debug circuitry:
 - using nrfjprog --reset
 - using JLinkExe : issue the command writeDP 1 0
 or with OpenOCD
 - issue the command halt
 - issue the command flash fillw 0x10001208 0xFFFFFF00 0x01
 - issue the command reset
 you can check if the debug port is enabled using the following code
 DWT->CYCCNT ? "NO":"YES"

Button

The button on the side of the PineTime is disabled by default. To enable it, drive the button out pin (P0.15) high.

While enabled, the button in pin (P0.13) will be high when the button is pressed, and low when it is not pressed.

Touch panel

The touch panel is controlled by a Hynitron CST816S chips. Unfortunately, there is not much information about this chip on the internet apart from the datasheet below and a reference driver. This is enough to implement a basic driver, but crucial information needed to implement advanced functionalities are missing (I²C protocol and registers, timings, power modes,...).

Pins

  • P0.10 : Reset
  • P0.28 : Interrupt (signal to the CPU when a touch event is detected)
  • P0.06 : I²C SDA
  • P0.07 : I²C SCL

I²C

  • Device address : 0x15
  • Frequency : from 10Khz to 400Khz

NOTE : The controller go to sleep when no event is detected. In sleep mode, the controller does not communicate on the I²C bus (it appears disconnected). So, for the communication to work, you need to tap on the screen so that the chip wakes-up.

Touch events

Touch informations are available in the 63 first registers of the controller. Remember : the device is in sleep mode when no touch event is detected. It means that you can read the register only when the touch controller detected an event. You can use the Interrupt pin to detect such event in the software.

These 63 bytes contain up to 10 touch point (X, Y, event type, pressure,...) :

Byte Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
0 ?
1 GestureID : (Gesture code ,

0x00: no gesture,

0x01: Slide down,

0x02: Slide up,

0x03: Slide left,

0x04: Slide right,

0x05: Single click,

0x0B: Double click,

0x0C: Long press)

2 ? Number of touch points
3 Event (0 = Down, 1 = Up, 2 = Contact) ? X (MSB) coordinate
4 X (LSB) coordinate
5 ? Touch ID Y (MSB) coordinate
6 Y (LSB) coordinate
7 Pressure (?)
8 Miscellaneous (?)

Bytes 3 to 8 are repeated 10 times (10*6 + 3 = 63 bytes).

NOTES

  • The touch controller seems to report only 1 touch point
  • Fields X, Y, Number of touch points and touch ID are updated. The others are always 0.

Registers

The reference driver specifies some registers and value, but there is no information about them:

Register Address Description
HYN_REG_INT_CNT 0x8F
HYN_REG_FLOW_WORK_CNT 0x91
HYN_REG_WORKMODE 0x00 0 = WORK, 0x40 = FACTORY
HYN_REG_CHIP_ID 0xA3
HYN_REG_CHIP_ID2 0x9F
HYN_REG_POWER_MODE 0xA5 0x05 = SLEEP
HYN_REG_FW_VER 0xA6
HYN_REG_VENDOR_ID 0xA8
HYN_REG_LCD_BUSY_NUM 0xAB
HYN_REG_FACE_DEC_MODE_EN 0xB0
HYN_REG_GLOVE_MODE_EN 0xC0
HYN_REG_COVER_MODE_EN 0xC1
HYN_REG_CHARGER_MODE_EN 0x8B
HYN_REG_GESTURE_EN 0xD0
HYN_REG_GESTURE_OUTPUT_ADDRESS 0xD3
HYN_REG_ESD_SATURATE 0xED 0xED

WARNING : Writing the SLEEP command (write 0x05 in HYN_REG_POWER_MODE) seems to freeze the controller (it returns only static values) until the battery is totally drained and the whole system reset. Analysis and debugging is more than welcome!

Manual / Articles

Development efforts

Project Homepage Project Source PineTime Implementations
FreeRTOS https://www.freertos.org https://sourceforge.net/projects/freertos/ JF002/Pinetime

kaythe/pinetime-os

Zephyr https://www.zephyrproject.org https://github.com/zephyrproject-rtos/zephyr
najnesnaj/pinetime-zephyr
SuperPrower/pinetime_zephyr_sample_fw
Dejvino/pinetime-hermes-firmware
mynewt https://mynewt.apache.org/about/ https://github.com/apache/mynewt-core lupyuen/pinetime-rust-mynewt
MbedOS https://os.mbed.com https://github.com/ARMmbed/mbed-os sethitow/mbed-pinetime
RIOT http://riot-os.org/ https://github.com/RIOT-OS/RIOT/ bosmoment/PineTime-apps
TinyGo https://tinygo.org https://github.com/tinygo-org/tinygo aykevl/go-smartwatch
MicroPython https://micropython.org/ https://github.com/micropython/micropython daniel-thompson/wasp-os
Bare Metal https://github.com/xriss/timecake xriss/timecake
AdaFruit bootloader https://github.com/adafruit/Adafruit_nRF52_Bootloader daniel-thompson/wasp-bootloader
UI concepts and drawings arteeh/pinetimeos

Datasheets and Schematics

Schematics

Note: The part number for the SPI FLASH in the schematic diagram is not correct, the PineTime features a larger external FLASH device, see below.

Component Datasheets

Community