Documentation for “Zerocat Chipflasher” as of Wed, 24 Jun 2026 07:28:14 +0200
Repository: git://zerocat.org/zerocat/projects/chipflasher.git
Version: v3.0.0-0-b445ef922
Branch: master
{{
______________________________________________________________________________
********************************************************* File starts here ***
Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.
Copyright (C) 2020, 2021, 2022, 2024, 2025, 2026 Kai Mertens
File pcb.spin --- Check PCB features.
This file is part of the Zerocat Chipflasher.
See end of file for terms of use.
******************************************************************************
}}
''
''
''# Included Compiler Configuration
# ifndef __PCB_SPIN_CFG__
# include "./pcb.spin.cfg"
# endif
''
''
''# Object Summary
OBJ 'This directive triggers the compiler to insert a summary.
''
''
''# Loaded Objects
''
time : "time" ''* time object
''
''
''# Included Files
''
''
''# Constants
CON
''
''## Sections in respect to PCB version
''
''* PCBv2.1, PCBv2.2
''* PCBv2.0
''* PCBv2
''* PCBv1.1
''* PCBv1.0
''* PCBv1
''* Common
''
''The PCB version is detected during runtime, that is why this object should
''set RAM locations to appropriate values:
''
''* RAM_PCB_VERSION
''* RAM_RST_INIHIBIT
''* RAM_ISMON_VSPI
''* RAM_ISMON_RPULL
''* RAM_ISMON_RST
''* RAM_MASK_CEn_AVAIL
''
''## PCBv2.1, PCBv2.2
''
''* SPI_CEn1_PCBv2_1 -- Second Enable Pin, active low
SPI_CEn1_PCBv2_1 = 1
''* SPI_RPULL -- Used to load C_pull and to read R_pull value
SPI_RPULL = 0
''* Hardcoded RC decay values for C_pull = 22nF, R_pull = 83..570 Ohm
RPULL_MIN = 83
RPULL_MAX = 570
'RPULL_MIN_22nF = 1133
'RPULL_MAX_22nF = 1975
'RPULL_MIN_22nF_X7R = 1122 'raw values range between 1119..1125
'RPULL_MAX_22nF_X7R = 1807 'raw values range between 1794..1819
'RPULL_MIN_22nF_X7R_3 = 3366 'raw values range between 3362..3370
'RPULL_MAX_22nF_X7R_3 = 5423 'raw values range between 5414..5432
RPULL_MIN_22nF_X7R_10 = 11221 'raw values range between 11216..11226
RPULL_MAX_22nF_X7R_10 = 18055 'raw values range between 18031..18098
''
''## PCBv2.0
''
''* SPI_CEn1_PCBv2_0 -- Second Enable Pin, active low
SPI_CEn1_PCBv2_0 = 0
''
''## PCBv2
''
''* RS232_RST -- Sense RST input from host
''* RST_INHIBIT -- Inhibit signal pin on board v2 for net RS232_RST
''* ADC_OUT -- Sigma-delta ADC circuit, counter output
''* ADC_CALIBRATION -- Sigma-delta ADC circuit, calibration pin, providing 0V/3.3V, tri-state when idle
''* ADC_IN -- Sigma-delta ADC circuit, counter input
''
RS232_RST = 24
RST_INHIBIT = 11
ADC_OUT = 27
ADC_CALIBRATION = 26
ADC_IN = 25
''* DIP Switch 1: RS232 Baudrate
''
'' open = H, closed = L
''
'' RS232 Baudrate | SWDIP_1
'' ----------------|-----------
'' 57600 | H
'' 115200 | L
''
SWDIP_1 = 18
''* DIP Switch 2: SPI Power-up Type
''
'' open = H, closed = L
''
'' Power-up Type | SWDIP_2
'' ----------------|-----------
'' one shot | H
'' pulses | L
''
SWDIP_2 = 19
''* DIP Switch 3: SPI Power-off Type
''
'' open = H, closed = L
''
'' Power-off Type | SWDIP_3
'' ----------------|-----------
'' auto | H
'' user | L
''
SWDIP_3 = 20
''* DIP Switch 4: SPI Mode
''
'' open = H, closed = L
''
'' SPI Mode | SWDIP_4
'' ----------|-----------
'' 0 | H
'' 3 | L
''
SWDIP_4 = 21
''* DIP Switches 5..6: SPI Clock Driver
''
'' open = H, closed = L
''
'' SPI Clock Driver | SWDIP_5 | SWDIP_6
'' ------------------|-----------|-----------
'' 25% | H | H
'' 50% | L | H
'' 75% | H | L
'' 100% | L | L
''
SWDIP_5 = 22
SWDIP_6 = 23
''
''## PCBv1.1
''
SPI_CABLEn_PCBv1_1 = 9 'This pin is used to detect the SPI cable since board-v1.1.0
''
''## PCBv1.0
''
SPI_CABLEn_PCBv1_0 = 10 'This pin is used to detect the SPI cable prior to board-v1.1.0
''
''## PCBv1
''
''* SPI_CEn1_PCBv1 -- Second Chip Enable Pin, active low
''
SPI_CEn1_PCBv1 = 0
''* RST_DISABLE -- Inhibit signal pin on board v1 for net RS232_RST
''
RST_DISABLE = 16
''* PCBv1_CONFIG -- Hardcoded DIP switch configuration for PCBv1 aka board-v1
''
'' This configuration can also be set per menu.
''
'' - RS232 baudrate: 115200
'' - SPI power-on: one shot
'' - SPI power-off: auto
'' - SPI clock: mode 3
'' - clock driver strength: 50%
''
PCBv1_CONFIG = %011001
''
''## Common
''
''* DIP Switches A and B: Board Version
''
'' Devkit: open = H, closed straight = L, closed angular = H
''
'' open = H, closed = L
''
'' Board Version | SWDIP_B | SWDIP_A
'' ---------------|-----------|-----------
'' V1 | L | L
'' V2 | L | H
'' V2.1 | L | H_delayed_40
'' V2.2 | L | H_delayed_20
'' V3 | H | L
'' V4 | H | H
''
'' On PCBv1, SWDIP_A is connected to GND via resistor.
''
'' On PCBv1, SWDIP_B is not connected but will hopefully read low at start.
''
'' On PCBv2.1 and PCBv2.2, SWDIP_A is connected to an RC network.
'' It can be detected by driving SWDIP_A low and then waiting for a low-to-high transition.
''
SWDIP_A = 16
SWDIP_B = 17
''* SPI Pins
SPI_CEn0 = 1 'First Chip Enable Pin
''* RS232 Pins
RS232_TX = 30 'RS232 TX (Transmit to Host) Pin
RS232_RX = 31 'RS232 RX (Receive from Host) Pin
''* SPI Modes
SPI_MODE_0 = 0
SPI_MODE_3 = 3
''
''
''# Globals
VAR
BYTE g_pcbversion
BYTE g_pcbconfig
''
''
''# Functions
PUB set_pcbversion (v)
'' Setter method for g_pcbversion.
g_pcbversion := v
PUB get_pcbversion : r
'' Getter method for g_pcbversion
RETURN g_pcbversion
PUB set_pcbconfig (v)
'' Setter method for g_pcbconfig.
g_pcbconfig := v
PUB get_pcbconfig : r
'' Getter method for g_pcbconfig
RETURN g_pcbconfig
PUB check_cable_SPI : r
'' Check SPI Cable:
''
'' FALSE = a) Cable not present or b) twisted plug
'' TRUE = Cable present
CASE g_pcbversion
$01: r := !(INA[SPI_CABLEn_PCBv1_0] <> FALSE)
OTHER: r := !(INA[SPI_CABLEn_PCBv1_1] <> FALSE)
PUB is_monitor_VSPI
'' Is SPI voltage monitor hardware available?
CASE g_pcbversion
$01, $11: RETURN FALSE
OTHER: RETURN TRUE
PUB is_monitor_RPULL
'' Is SPI R_pull monitor hardware available?
'Is monitor hardware available for SPI R_pull?
CASE g_pcbversion
$01, $11, $02: RETURN FALSE
OTHER: RETURN TRUE
PUB is_monitor_RST
'' Is pin RS232_RST monitored?
CASE g_pcbversion
$02: RETURN TRUE
OTHER: RETURN FALSE
PUB is_RS232_CTS
'' Is pin RS232_CTS available?
CASE g_pcbversion
$01, $11, $02: RETURN FALSE
OTHER: RETURN TRUE
PUB get_RST_INHIBIT
'' Which pin is used to inhibit net RS232_RST?
'Which pin is used to inhibit net RS232_RST?
CASE g_pcbversion
$01, $11: RETURN RST_DISABLE
OTHER: RETURN RST_INHIBIT
PUB get_MASK_CEn_AVAIL
'' Which pins are used to enable SPI CE#?
CASE g_pcbversion
$01, $11: RETURN (|<SPI_CEn0 | |<SPI_CEn1_PCBv1)
$02: RETURN (|<SPI_CEn0 | |<SPI_CEn1_PCBv2_0)
$12: RETURN (|<SPI_CEn0 | |<SPI_CEn1_PCBv2_1)
OTHER: RETURN |<SPI_CEn0
PUB get_RPULL : r
'' Check value of R_pull,
'' which must not be smaller than 83 Ohm if driven by one pin.
'set up Counter A for Pos. Detection on SPI_RPULL
FRQA := 0
PHSA := 0
CTRA := %0_01000_000 << 23 + 0 << 9 + SPI_RPULL
'prepare SPI_RPULL
OUTA[SPI_RPULL]~~
REPEAT 10
'load C_pull for 10us
DIRA |= (|<SPI_RPULL | get_MASK_CEn_AVAIL)
time.sleep_10us
'stop loading, count decay time
FRQA := 1
DIRA &= !(|<SPI_RPULL) 'take this execution time into account
time.sleep_50us
FRQA := 0
DIRA &= !get_MASK_CEn_AVAIL
'restore SPI_RPULL
OUTA[SPI_RPULL]~
'stop Counter A
CTRA := %0_00000_000 << 23 + 0 << 9 + SPI_RPULL
'adjust result, or ...
'r := ((PHSA - RPULL_MIN_22nF_X7R) * (RPULL_MAX - RPULL_MIN) / (RPULL_MAX_22nF_X7R - RPULL_MIN_22nF_X7R)) + RPULL_MIN
'r := ((PHSA - RPULL_MIN_22nF_X7R_3) * (RPULL_MAX - RPULL_MIN) / (RPULL_MAX_22nF_X7R_3 - RPULL_MIN_22nF_X7R_3)) + RPULL_MIN
r := ((PHSA - RPULL_MIN_22nF_X7R_10) * (RPULL_MAX - RPULL_MIN) / (RPULL_MAX_22nF_X7R_10 - RPULL_MIN_22nF_X7R_10)) + RPULL_MIN
'... calibrate:
'r := PHSA
PUB sample_pcbversion : vboard | sw
'' Retrieve board version from PCB, read SWDIP_A and SWDIP_B:
''
'' Devkit: open = H, closed straight = L, closed angular = H
''
'' open = H, closed = L
''
'' SWDIP_B | SWDIP_A | PCB version | Return Value | device
'' ---------|------------------|---------------|-----------------|---------------------------------
'' L | L | board-v1 | $0001 |
'' L | L | board-v1.1 | $0011 | Chipflasher `board-edition-1 ''
'' L | H | board-v2.0 | $0002 | Chipflasher v2
'' L | H_delayed_40 | board-v2.1 | $0012 |
'' L | H_delayed_20 | board-v2.2 | $0022 | Chipflasher v2.1
'' H | L | board-v3 | $0003 |
'' H | H | board-v4 | $0004 |
''
'' On board-v1, SWDIP_A is connected to GND via resistor.
''
'' On board-v1, SWDIP_B is not connected but will hopefully read low at start.
''
'' On board-v2.1 and board-v2.2, SWDIP_A is connected to an RC network.
'' It can be detected by driving SWDIP_A low and then waiting for a low-to-high transition.
'drive SWDIP_A low
DIRA[SWDIP_A]~~
time.sleep_husec(10)
'read SWDIP_A: sample #0, delay, sample #1, delay, sample #2
DIRA[SWDIP_A]~
'sample #0
sw := INA[SWDIP_A] << 2
'sample #1
'delay must be bigger than 1.2msec with 23.5k and 100nF
'delay must be smaller than 2.5msec with 47k and 100nF
time.sleep_husec(20)
sw |= INA[SWDIP_A] << 1
'sample #2
time.sleep_husec(20)
sw |= INA[SWDIP_A] << 0
'get major board version
vboard := INA[SWDIP_B..SWDIP_A] + 1
'set minor board version
CASE vboard
1:
'test for board version below v1.1
CASE INA[10..9]
%01: 'cable on board-v1.0
OTHER: 'a) no cable or b) cable twisted or c) cable on board-v1.1
vboard |= 1 << 4 'set v1 subversion to 1
2:
CASE sw
%000: vboard |= 0 << 4
%001: vboard |= 1 << 4
%011: vboard |= 2 << 4
PUB sample_pcbconfig : cfg
'' Return six configuration bits in respect to parameter `vboard':
'' If `vboard' is 1, return the value of `PCBv1_CONFIG',
'' otherwise read DIP switches on PCB.
CASE g_pcbversion
$01, $11: cfg := PCBv1_CONFIG 'PCBv1: hardcode DIP switch
OTHER: cfg := (!INA[SWDIP_6..SWDIP_1]) 'PCBv2: read DIP switch
PUB get_SPI_power_on_type
'' Return TRUE or FALSE according to bit position 2 of parameter `cfg',
'' corresponding to this translation:
''
'' bp2
'' ---
'' 0 = one shot SPI power-up (FALSE)
'' 1 = pulsed SPI power-up (TRUE)
# ifdef _CFG_SPIPWRON_ONESHOT
RETURN FALSE
# endif
# ifdef _CFG_SPIPWRON_PULSES
RETURN TRUE
# endif
# ifdef _CFG_SPIPWRON_DIPSW
RETURN (g_pcbconfig & %000010) <> FALSE
# endif
PUB get_SPI_power_off_type
'' Return TRUE or FALSE according to bit postion 3 of parameter `cfg',
'' corresponding to this translation:
''
'' bp3
'' ---
'' 0 = automatic suspend, if required (FALSE)
'' 1 = static power, suspend inhibited (TRUE)
# ifdef _CFG_SPIPWROFF_AUTO
RETURN FALSE
# endif
# ifdef _CFG_SPIPWROFF_USER
RETURN TRUE
# endif
# ifdef _CFG_SPIPWROFF_DIPSW
RETURN (g_pcbconfig & %000100) <> FALSE
# endif
PUB get_SPI_power_config
'' Return value 0..3 according to bit positions 2 and 3 of parameter `cfg',
'' corresponding to this translation table:
''
'' bp2 | bp3
'' ----|----
'' 0 | 0 = one shot, auto
'' 1 | 0 = pulses, auto
'' 0 | 1 = one shot, static
'' 1 | 1 = pulses, static
RETURN (g_pcbconfig & %000110) >> 1
PUB get_SPI_mode
'' Return SPI Mode according to bit position 4 of parameter `cfg':
'' 0 -> Mode 0, 1 -> Mode 3
'' Alternatively, return modes according to preprocessor directive.
# ifdef _CFG_SPIMODE_0
RETURN SPI_MODE_0
# endif
# ifdef _CFG_SPIMODE_3
RETURN SPI_MODE_3
# endif
# ifdef _CFG_SPIMODE_DIPSW
CASE (g_pcbconfig & %001000) >> 3
0: RETURN SPI_MODE_0
1: RETURN SPI_MODE_3
# endif
PUB get_clk_driver
'' Return 0..3 according to bit positions 5 and 6 of parameter `cfg'.
'' Return values correspond to 25%(0)..100%(3) SPI clock driver strength.
'' Alternatively, return values according to preprocessor directive.
# ifdef _CFG_SPICLK_100
RETURN %11
# endif
# ifdef _CFG_SPICLK_75
RETURN %10
# endif
# ifdef _CFG_SPICLK_50
RETURN %01
# endif
# ifdef _CFG_SPICLK_25
RETURN %00
# endif
# ifdef _CFG_SPICLK_DIPSW
RETURN (g_pcbconfig & %110000) >> 4
# endif
PUB get_baudrate
'' Return baudrate according to bit position 1 of parameter `cfg':
'' 0 -> 57600, 1 -> 115200
'' Alternatively, return baudrate according to preprocessor directive:
'' 38400, 230400
# ifdef _CFG_RS232_230400
RETURN 230400
# endif
# ifdef _CFG_RS232_115200
CASE g_pcbconfig & %000001
0: RETURN 57600
1: RETURN 115200
# endif
# ifdef _CFG_RS232_57600
CASE g_pcbconfig & %000001
0: RETURN 57600
1: RETURN 115200
# endif
# ifdef _CFG_RS232_38400
RETURN 38400
# endif
{{
******************************************************************************
Terms of Use:
Zerocat Chipflasher is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Zerocat Chipflasher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with Zerocat Chipflasher. If not, see <http://www.gnu.org/licenses/>.
************************************************************** End of File ***
}}