abse/smart-ring-flex

A tscircuit package created by abse.

Version
0.0.24
License
unset
Stars
0

firmware/onboard-programmer/upstream/src/system.h

// ===================================================================================
// Basic System Functions for CH551, CH552 and CH554                          * v1.6 *
// ===================================================================================
//
// System clock (CLK)functions available:
// --------------------------------------
// CLK_config()             set system clock frequency according to F_CPU
// CLK_external()           set external crystal as clock source
// CLK_internal()           set internal oscillator as clock source
//
// Watchdog Timer (WDT) functions available:
// -----------------------------------------
// WDT_start()              start watchdog timer with full period
// WDT_stop()               stop watchdog timer
// WDT_reset()              reload watchdog timer with full period
// WDT_set(time)            reload watchdog timer with specified time in ms
// WDT_feed(value)          reload watchdog timer with specified value
//
// Reset (RST) and bootloader functions available:
// -----------------------------------------------
// RST_now()                perform software reset
// RST_keep(value)          keep this value after RESET
// RST_getKeep()            read the keeped value
// RST_wasWDT()             check if last RESET was caused by watchdog timer
// RST_wasPIN()             check if last RESET was caused by RST PIN
// RST_wasPWR()             check if last RESET was caused by power-on
// RST_wasSOFT()            check if last RESET was caused by software
//
// BOOT_now()               enter bootloader
//
// Sleep functions available:
// --------------------------
// SLEEP_now()              put device into sleep
//
// WAKE_enable(source)      enable wake-up from sleep source (sources see below)
// WAKE_disable(source)     disable wake-up from sleep source
// WAKE_all_disable()       disable all wake-up sources
//
// WAKE_USB_enable()        enable wake-up by USB event
// WAKE_RXD0_enable()       enable wake-up by RXD0 low level
// WAKE_RXD1_enable()       enable wake-up by RXD1 low level
// WAKE_P13_enable()        enable wake-up by pin P1.3 low level
// WAKE_P14_enable()        enable wake-up by pin P1.4 low level
// WAKE_P15_enable()        enable wake-up by pin P1.5 low level
// WAKE_RST_enable()        enable wake-up by pin RST high level
// WAKE_INT_enable()        enable wake-up by pin P3.2 edge or pin P3.3 low level
//
// WAKE_USB_disable()       disable wake-up by USB event
// WAKE_RXD0_disable()      disable wake-up by RXD0 low level
// WAKE_RXD1_disable()      disable wake-up by RXD1 low level
// WAKE_P13_disable()       disable wake-up by pin P1.3 low level
// WAKE_P14_disable()       disable wake-up by pin P1.4 low level
// WAKE_P15_disable()       disable wake-up by pin P1.5 low level
// WAKE_RST_disable()       disable wake-up by pin RST high level
// WAKE_INT_disable()       disable wake-up by pin P3.2 edge or pin P3.3 low level
//
// Wake-up from SLEEP sources:
// ---------------------------
// WAKE_USB                 wake-up by USB event
// WAKE_RXD0                wake-up by RXD0 low level
// WAKE_RXD1                wake-up by RXD1 low level
// WAKE_P13                 wake-up by pin P1.3 low level
// WAKE_P14                 wake-up by pin P1.4 low level
// WAKE_P15                 wake-up by pin P1.5 low level
// WAKE_RST                 wake-up by pin RST high level
// WAKE_INT                 wake-up by pin P3.2 edge or pin P3.3 low level
//
// Interrupt (INT) functions available:
// ------------------------------------
// INT_enable()             global interrupt enable
// INT_disable()            global interrupt disable
// INT_ATOMIC_BLOCK { }     execute block without being interrupted
//
// 2023 by Stefan Wagner:   https://github.com/wagiminator

#pragma once
#include <stdint.h>
#include "ch554.h"

// ===================================================================================
// System Clock (CLK) Functions
// ===================================================================================
inline void CLK_config(void) {
  SAFE_MOD = 0x55;
  SAFE_MOD = 0xAA;                              // enter safe mode
  
  #if F_CPU == 32000000
    __asm__("orl _CLOCK_CFG, #0b00000111");     // 32MHz
  #elif F_CPU == 24000000
    __asm__("anl _CLOCK_CFG, #0b11111000");
    __asm__("orl _CLOCK_CFG, #0b00000110");     // 24MHz	
  #elif F_CPU == 16000000
    __asm__("anl _CLOCK_CFG, #0b11111000");
    __asm__("orl _CLOCK_CFG, #0b00000101");     // 16MHz	
  #elif F_CPU == 12000000
    __asm__("anl _CLOCK_CFG, #0b11111000");
    __asm__("orl _CLOCK_CFG, #0b00000100");     // 12MHz
  #elif F_CPU == 6000000
    __asm__("anl _CLOCK_CFG, #0b11111000");
    __asm__("orl _CLOCK_CFG, #0b00000011");     // 6MHz	
  #elif F_CPU == 3000000
    __asm__("anl _CLOCK_CFG, #0b11111000");
    __asm__("orl _CLOCK_CFG, #0b00000010");     // 3MHz	
  #elif F_CPU == 750000
    __asm__("anl _CLOCK_CFG, #0b11111000");
    __asm__("orl _CLOCK_CFG, #0b00000001");     // 750kHz	
  #elif F_CPU == 187500
    __asm__("anl _CLOCK_CFG, #0b11111000");     // 187.5kHz		
  #else
    #warning F_CPU invalid or not set
  #endif

  SAFE_MOD = 0x00;                              // terminate safe mode
}

inline void CLK_external(void) {
  SAFE_MOD = 0x55;
  SAFE_MOD = 0xAA;                              // enter safe mode
  CLOCK_CFG |=  bOSC_EN_XT;                     // enable external crystal
  CLOCK_CFG &= ~bOSC_EN_INT;                    // turn off internal oscillator
  SAFE_MOD = 0x00;                              // terminate safe mode
}

inline void CLK_inernal(void) {
  SAFE_MOD = 0x55;
  SAFE_MOD = 0xAA;                              // enter safe mode
  CLOCK_CFG |=  bOSC_EN_INT;                    // turn on internal oscillator
  CLOCK_CFG &= ~bOSC_EN_XT;                     // disable external crystal
  SAFE_MOD = 0x00;                              // terminate safe mode
}

// ===================================================================================
// Watchdog Timer (WDT) Functions
// ===================================================================================
#define WDT_reset()       WDOG_COUNT = 0
#define WDT_feed(value)   WDOG_COUNT = value
#define WDT_set(time)     WDOG_COUNT = (uint8_t)(256 - ((F_CPU / 1000) * time / 65536))

inline void WDT_start(void) {
  WDOG_COUNT  = 0;
  SAFE_MOD    = 0x55;
  SAFE_MOD    = 0xAA;
  GLOBAL_CFG |= bWDOG_EN;
  SAFE_MOD    = 0x00;
}

inline void WDT_stop(void) {
  SAFE_MOD    = 0x55;
  SAFE_MOD    = 0xAA; 
  GLOBAL_CFG &= ~bWDOG_EN;
  SAFE_MOD    = 0x00;
}

// ===================================================================================
// Reset (RST) Functions
// ===================================================================================
#define RST_keep(value)   RESET_KEEP = value
#define RST_getKeep()     (RESET_KEEP)
#define RST_wasWDT()      ((PCON & MASK_RST_FLAG) == RST_FLAG_WDOG)
#define RST_wasPIN()      ((PCON & MASK_RST_FLAG) == RST_FLAG_PIN)
#define RST_wasPWR()      ((PCON & MASK_RST_FLAG) == RST_FLAG_POR)
#define RST_wasSOFT()     ((PCON & MASK_RST_FLAG) == RST_FLAG_SW)

inline void RST_now(void) {
  SAFE_MOD    = 0x55;
  SAFE_MOD    = 0xAA;
  GLOBAL_CFG |= bSW_RESET;
}

// ===================================================================================
// Bootloader (BOOT) Functions
// ===================================================================================
inline void BOOT_now(void) {
  __asm
    ljmp #BOOT_LOAD_ADDR
  __endasm;
}

inline void BOOT_prepare(void) {
  ES = 0;
  PS = 0;
  TMOD       = 0;
  P1_DIR_PU  = 0;
  P1_MOD_OC  = 0;	
  P1         = 0xFF;
  USB_INT_EN = 0;
  USB_CTRL   = 0x06;
  EA = 0;
}

// ===================================================================================
// Sleep Functions
// ===================================================================================
#define SLEEP_now()   PCON |= PD

#define WAKE_USB      bWAK_BY_USB     // wake-up by USB event
#define WAKE_RXD0     bWAK_RXD0_LO    // wake-up by RXD0 low level
#define WAKE_RXD1     bWAK_RXD1_LO    // wake-up by RXD1 low level
#define WAKE_P13      bWAK_P1_3_LO    // wake-up by pin P1.3 low level
#define WAKE_P14      bWAK_P1_4_LO    // wake-up by pin P1.4 low level
#define WAKE_P15      bWAK_P1_5_LO    // wake-up by pin P1.5 low level
#define WAKE_RST      bWAK_RST_HI     // wake-up by pin RST high level
#define WAKE_INT      bWAK_P3_2E_3L   // wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level

#define WAKE_enable(source)     WAKE_CTRL |=  source
#define WAKE_disable(source)    WAKE_CTRL &= ~source
#define WAKE_all_disable()      WAKE_CTRL  =  0

#define WAKE_USB_enable()       WAKE_CTRL |=  bWAK_BY_USB
#define WAKE_RXD0_enable()      WAKE_CTRL |=  bWAK_RXD0_LO
#define WAKE_RXD1_enable()      WAKE_CTRL |=  bWAK_RXD1_LO
#define WAKE_P13_enable()       WAKE_CTRL |=  bWAK_P1_3_LO
#define WAKE_P14_enable()       WAKE_CTRL |=  bWAK_P1_4_LO
#define WAKE_P15_enable()       WAKE_CTRL |=  bWAK_P1_5_LO
#define WAKE_RST_enable()       WAKE_CTRL |=  bWAK_RST_HI
#define WAKE_INT_enable()       WAKE_CTRL |=  bWAK_P3_2E_3L

#define WAKE_USB_disable()      WAKE_CTRL &= ~bWAK_BY_USB
#define WAKE_RXD0_disable()     WAKE_CTRL &= ~bWAK_RXD0_LO
#define WAKE_RXD1_disable()     WAKE_CTRL &= ~bWAK_RXD1_LO
#define WAKE_P13_disable()      WAKE_CTRL &= ~bWAK_P1_3_LO
#define WAKE_P14_disable()      WAKE_CTRL &= ~bWAK_P1_4_LO
#define WAKE_P15_disable()      WAKE_CTRL &= ~bWAK_P1_5_LO
#define WAKE_RST_disable()      WAKE_CTRL &= ~bWAK_RST_HI
#define WAKE_INT_disable()      WAKE_CTRL &= ~bWAK_P3_2E_3L

// ===================================================================================
// Interrupt (INT) Functions
// ===================================================================================
#define INT_enable()        EA = 1
#define INT_disable()       EA = 0
#define INT_ATOMIC_BLOCK    for(EA=0;!EA;EA=1)