import time
time.sleep(0.1) # Wait for USB to become ready

print("Hello, Pi Pico!")

#-------------------------------------------------------
#-------------------------------------------------------

import rp2
from machine import Pin, PWM
import utime
import math
import sys

# Define key and LED pins
KEY1 = Pin(0, Pin.IN, Pin.PULL_UP)
KEY2 = Pin(1, Pin.IN, Pin.PULL_UP)   # KEY2 for turning backlight ON/OF
# 割り込みフラグ
falling_edge_flag = False
rising_edge_flag = False
# 立下りエッジの処理
def button_falling_handler(pin):
    global falling_edge_flag
    falling_edge_flag = True  # 立下りエッジのフラグを設定
# 立上りエッジの処理
def button_rising_handler(pin):
    global rising_edge_flag
    rising_edge_flag = True  # 立上りエッジのフラグを設定
# 割り込みの設定
#KEY2.irq(trigger=Pin.IRQ_FALLING, handler=button_falling_handler)  # 立下りエッジ
#KEY2.irq(trigger=Pin.IRQ_RISING, handler=button_rising_handler)  # 立上りエッジ
# 立下りエッジの処理
def button_handler(pin):
    global falling_edge_flag
    global rising_edge_flag
    utime.sleep_ms(20)  # 50msの遅延
    if KEY2.value() == 0:  # スイッチが押されているか確認
        falling_edge_flag = True  # 立下りエッジのフラグを設定
    elif KEY2.value() == 1:  # スイッチが離されているか確認
        rising_edge_flag = True  # 立上りエッジのフラグを設定
# 割り込みの設定
KEY2.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=button_handler)  # 両エッジ

led_pin = Pin(25, Pin.OUT)
#led_state = False
Vddio = Pin(4, mode=Pin.OUT, value=0)
Vddio_2 = Pin(3, mode=Pin.OUT, value=1)
Vled = Pin(5, mode=Pin.OUT, value=0)

status_pin = Pin(18, mode=Pin.OUT, value=0)     # 使用目的は?

cs_pin = Pin(13, mode=Pin.OUT, value=0)
pwm = Pin(9, mode=Pin.OUT, value=0)

status = 0      # Initialize status to 0        # line785と重複、意図は?
loop_count = 0  # Initialize loop counter       # 使用していません!変数の意図は?
button_press_count = 0                          # 使用していません!変数の意図は?

t1_us = 50      # 100 us; make sure all sclk are sent before SCS is setted High level
#the time from VLED low to VDD low is t2_s(VLED low to CS low,1ms) + t3_s(CS low to VDD low,50ms), it's setted 51ms
t2_ms = 1       # 1ms
t3_ms = 50      # the time from the discharge of vled to vddio 
# adjust data from 8 bit to 32 bit, if you want the data to be sent in units of 8 bits, the number here should be changed to 8.
# 8 bit → 8; 16 bit → 16; 24 bit → 24; 32 bit → 32;
#The reason for sending data in 32-bit units is that it is easier to understand and the most efficient way to send the total write_blocking data.
#On the other hand, if data is sent in 8-bit/6-bit/24-bit units, there will be losses in the SCK waveform.
get_threshold = 32
# Shift the data ___bit to the left, if you want the data to be sent in units of 8 bits, the number here should be changed to 24.
# 32 bit → 0; 24 bit → 8; 16 bit → 16; 8 bit → 24;
get_shift_value = 0

loop_time = 1              # set loop 1 time            # 使用していません!変数の意図は?
delay_in_seconds = 1 * 600 # set 10000 hours (during LED on) → 10000* 3600(10000→10000 times, 3600→3600s/1H), one second longer     # 使用していません!変数の意図は?
led_off_delay = 5          # set 5 s (during LED off)   # 使用していません!変数の意図は?

duty_value_1 = 33          # 33% → 33
duty_value_2 = 40          # 40% → 40
duty_value_100 = 110       # 100% → 110
duty_value_10 = 10         # 10% → 10
duty_value_11_9 = 11.9     # 11.9% → 11.9
vsy_freq = 60
osc_freq = 4000000         # oscillator frequency(P1→3333333[3.33MHz],period→300ns:period; P2→4000000[4MHz], period→250ns)
time_res = 2               # time resolution(P1=1, P2=2)
#Sends data in units of 4
chunk_size = 4             # 8 bit → 1; 16 bit → 2; 24 bit → 3; 32 bit → 4;  
SPECIAL_VALUE = [0xC8, 0x85]    # 使用していません!リスト化の意図は?
# Setting the Threshold of VC
SLDET_1 = 0x40               # 0xC0(7.5V), 0x80(4.65V), 0x40(2.5V), 0x00(2.0V)
SLDET_2 = 0x00               # 0xC0(7.5V), 0x80(4.65V), 0x40(2.5V), 0x00(2.0V)
board_type = "Unknown" 


def combine_hex_elements(lst, chunk_size):
    add_len = chunk_size - (len(lst) % chunk_size)
    lst.extend([0] * add_len)
    result = []
    for i in range(0, len(lst), chunk_size):
        combined = 0
        for byte in lst[i:i + chunk_size]:
            combined = (combined << 8) | byte
        result.append(combined)
    return result

def write_blocking_pwm(adr_header, duty):
    pwm_dec = math.ceil(duty / 100 * osc_freq / time_res / vsy_freq)  # 切り上げ
#    pwmdata = [pwm_dec // 256, pwm_dec % 256]
    pwmdata = [pwm_dec >> 8, pwm_dec & 255]        # 動作確後どちらが良いか判断して下さい。
    adr_header.extend(pwmdata * 38)
    wdata = combine_hex_elements(adr_header + filler, chunk_size)
    pio_spi.write_blocking(wdata)
    utime.sleep_ms(32)


def iLED(att3,att2,att1):
    att3 = att3 - 69 if att3 > 69 else 0
    att2 = att2 - 69 if att2 > 69 else 0
    att1 = att1 - 69 if att1 > 69 else 0
    att = ((((att3 << 5) + att2) << 5) + att1)
    iLEDnH = att >> 8
    iLEDnL = att & 255
    return (iLEDnH, iLEDnL)


# Define PIO program
@rp2.asm_pio(
    out_shiftdir=0,
    in_shiftdir=0,  #PIO.SHIFT_LEFT,
    autopull=True,
    pull_thresh=get_threshold,  #8,
    autopush=True,
    push_thresh=get_threshold,  #8,
    sideset_init=(rp2.PIO.OUT_LOW),
    out_init=rp2.PIO.OUT_LOW)

def spi_cpha0():
    set(x, 6)
    wrap_target()
    pull(ifempty)            .side(0x0)   [1]
    label("bitloop")
    out(pins, 1)             .side(0x0)   [1]  # Control MOSI high and low levels here
    in_(pins, 1)             .side(0x1)
    jmp(x_dec, "bitloop")    .side(0x1)

    out(pins, 1)             .side(0x0)
    set(x, 6)                .side(0x0)
    in_(pins, 1)             .side(0x1)
    jmp(not_osre, "bitloop") .side(0x1)

#    nop()                    .side(0x0)   [1]
    wrap()

class PIOSPI:
#    def __init__(self, sm_id, pin_mosi, pin_miso, pin_sck, cs_pin, cpha=False, cpol=False, freq=2000000):
    def __init__(self, sm_id, pin_mosi, pin_miso, pin_sck, cpha=False, cpol=False, freq=2000000):
        assert(not(cpol or cpha))
#        self._sm = rp2.StateMachine(sm_id, spi_cpha0, freq=4*freq,
#                                    sideset_base=Pin(cs_pin),
#                                    out_base=Pin(pin_mosi),
#                                    in_base=Pin(pin_miso),
#                                    set_base=Pin(pin_mosi))
        self._sm = rp2.StateMachine(sm_id, spi_cpha0, freq=4*freq,
                                    sideset_base=Pin(pin_sck),
                                    out_base=Pin(pin_mosi),
                                    in_base=Pin(pin_miso))
        MISO = Pin(pin_miso, Pin.IN)
#         self._sm.active(1)
#        self._cs = Pin(cs_pin, Pin.OUT)
        # The CS here is defined by the PIO as pin 9, but actually the CS is defined and used by the GPIO as pin 13;Because VSYNC (#9) in the GPIO is signaling suspiciously once before KEY1 is pressed, to fix this one bug, I'll use the PIO to pull cs low
#        self._cs.value(0)  # Initialize CS to low level(vsync level will )
        self._sm.active(1)
        
#    def write_read_blocking(self, wdata):
#        cs_pin.value(0)
#        rwbit=(wdata[0]>>23) & 0x0001
#        rdata = []
#        if rwbit==1:
#            for b in wdata:
#                self._sm.put(b << get_shift_value)
#                rdata.append(self._sm.get())
#        else:
#            for b in wdata:
#                self._sm.put(b << get_shift_value)
#                self._sm.get()
#        utime.sleep_us(t1_us)
#        cs_pin.value(1)
#        return rdata
    
    def write_read_blocking(self, wdata):
        cs_pin.value(0)
        rdata = []
        for b in wdata:
            self._sm.put(b << get_shift_value)
            rdata.append(self._sm.get())
        utime.sleep_us(t1_us)
        cs_pin.value(1)
        return rdata
    
    def write_blocking(self, wdata):
        cs_pin.value(0)
#        self._sm.restart()
        for b in wdata:
            self._sm.put(b << get_shift_value)
            self._sm.get()                      # dummy
        utime.sleep_us(t1_us)
        cs_pin.value(1)
#        utime.sleep_ms(1)

#    def read_blocking(self, n):
#        self.start()
#        data = []
#        for i in range(n):
#            data.append(self._sm.get() & 0x4F)
#        self.close()
#        return data

# Initialize PIO SPI
#pio_spi = PIOSPI(0, 11, 19, 10, 9)      # 0→sm_id,11→MOSI,19→MISO,10→SCK,9→CS(Not used)
pio_spi = PIOSPI(0, 11, 12, 10)          # 0→sm_id,11→MOSI,12→MISO,10→SCK,13→CS(Not used)


# filler Data
#filler_byte =[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    # filler byte #1~8
#              0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    # filler byte #9~16
#              0x00,0x00,0x00,0x00,0x00]                   # filler byte #17~21(devices-1)
#filler = filler_byte[0:23]
filler = [0x00] * 22        # filler byte:(devices-1)


# SW_RESET (0x24)
sw_reset = [0x3E, 0x01, 0x24,   # Broadast(Write with Same data) 1 address from 0x24(SW_RESET)
            0x80, 0x00          # In Page 51 of datasheet, , 0x8000 is set to enable SW_RESET (1) in the CNFG_SYS2 (0x24).
           ]
#sw_reset = sw_reset[0:7] + filler
sw_reset.extend(filler)
res_data = combine_hex_elements(sw_reset, chunk_size)

# Device Enumeration/Auto-Addressing
dev_enum = [0xC0, 0x01, 0x07, 0x16]     # 'Enumeration in a 22-Device System' setting in Page 18
dev_enum.extend(filler)
enumeration_data = combine_hex_elements(dev_enum, chunk_size)

# CNFG_SYS1(R23h), CNFG_SYS2(R24h), CNFG_MASK(R25h)
set23_25 = [0x3E, 0x03, 0x23,   # Broadast(Write with Same data) 3 address from 0x23 to 0x25
            0x00, 0x88,  # 0x23=0x0088, FPSFT_ENABLE(bit 6) in 0x88 should be disable(set bit 6→0) first, FPSFT_SET(bit 5:4) should be set 0x0 (default value)
            0x00, 0x03,  # 0x24=0x0003 in the right side means change to 8 scan (SCAN sets are in page 52 of datasheet);SNK_ delay settings in page 51 & 52 of datasheet, DELAY OPTION(1:0)→0x0: 8μs per LSb; 0x1: Minimum pulse width 500ns 
            0x00, 0xC7   # 0x25=0x00C7→enable all the functions in page 52 of the datasheet.
           ]
set23_25.extend(filler)
s23_25 = combine_hex_elements(set23_25, chunk_size)

# SNKSET_1(R29h)
SLdet_1 = [   0x3E, 0x01, 0x29,   # Broadast(Write with Same data) 1 address from 0x29(SNKSET)
            SLDET_1, 0x00]        # threshold of VC, [15:14]SLDET=1(2.5V)
SLdet_1.extend(filler)
R29h_SLDET_1 = combine_hex_elements(SLdet_1, chunk_size)              

# SNKSET_2(R29h)
SLdet_2 = [   0x3E, 0x01, 0x29,   # Broadast(Write with Same data) 1 address from 0x29(SNKSET)
            SLDET_2, 0x00]        # threshold of VC, [15:14]SLDET=0(2.0V)
SLdet_2.extend(filler)
R29h_SLDET_2 = combine_hex_elements(SLdet_2, chunk_size)              

# CNFG_ILED(R17h)
set_17 = [  0x3E, 0x01, 0x17,   # Broadast(Write with Same data) 1 address from 0x17(CNFG ILED)
            0x02, 0x20          # default 0x17 = 0x0220(peak current:10mA); 0x020C(peak current:5mA)
         ]
set_17.extend(filler)
s17 = combine_hex_elements(set_17, chunk_size)

# DISABLE1_16(R14h)
set_14 = [  0x3F, 0x01, 0x14,   # Broadast(Write with Different Data) 1 address from 0x14(DISABLE1_16)
            0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,# Dev#1~7;  enable SNK16~1
            0x00,0x02, 0x00,0x02, 0x00,0x02,                                            # Dev#8~10;  disable SNK2 (DISABLE1_16 (0x14) in page 38 of the datasheet)
            0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,           # Dev#11~16; enable SNK16~1
            0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00            # Dev#17~22; enable SNK16~1
         ]
set_14.extend(filler)
s14 = combine_hex_elements(set_14, chunk_size)

set_16 = [  0x3F, 0x01, 0x16,   # Broadast(Write with Different Data) 1 address from 0x16(DISABLE33_38)
            0x00,0x20, 0x00,0x20, 0x00,0x20, 0x00,0x20, 0x00,0x20, 0x00,0x20,   # Dev#1~6;  disable SNK38 (DISABLE33_38 (0x16) in page 38 of the datasheet)
            0x00,0x20, 0x00,0x20, 0x00,0x20, 0x00,0x20, 0x00,0x20, 0x00,0x20,   # Dev#7~12; disable SNK38 (DISABLE33_38 (0x16) in page 38 of the datasheet)
            0x00,0x00, 0x00,0x00, 0x00,0x00,                                    # Dev#13~15; enable SNK38~33
            0x00,0x20, 0x00,0x20,                                               # Dev#16~17; disable SNK38
            0x00,0x00,                                                          # Dev#18; enable SNK38~33
            0x00,0x20,                                                          # Dev#19; disable SNK38
            0x00,0x00,                                                          # Dev#20; enable SNK38~33
            0x00,0x20,                                                          # Dev#21; disable SNK38
            0x00,0x00                                                           # Dev#22; enable SNK38~33
         ]
set_16.extend(filler)
s16 = combine_hex_elements(set_16, chunk_size)

set_ILEDn = [   0x3E, 0x0D, 0x2B,   # Broadast(Write with Same data) 13 address from 0x2B to 0x37(ILEDn)
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x2B=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56 
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x2C=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x2D=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x2E=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x2F=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x30=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x31=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x32=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x33=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x34=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x35=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED(84,84,84)[0], iLED(84,84,84)[1],   # 0x36=0x3DEF; 3DEF→putted three 0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
                iLED( 0,84,84)[0], iLED( 0,84,84)[1],   # 0x37=0x01EF; 01EF→putted two   0x0F(Individual Channel Current Settings in p13 of the datasheet) together according to ILED3_1 (0x2B) on page 56
            ]                       # Because it only has 10 bits in ILED38_37 (0x37) on page 63 of the datasheet
set_ILEDn.extend(filler)
ILEDn = combine_hex_elements(set_ILEDn, chunk_size)

GBL_PWM = [ 0x3E, 0x01, 0x74,   # Broadast(Write with Same data) 1 address from 0x74(GBL_PWM_LOW16_VWDPORT)
            0x00, 0x00          # 0% (change to 0x0000 from 0x1388(default)) 
            ]
GBL_PWM.extend(filler)
GBL_PWM0 = combine_hex_elements(GBL_PWM, chunk_size)



delay = [   0x3E, 0x0D, 0x66,   # Broadast(Write with Same data) 13 address from 0x66~0x72(DELAY)
            0x08, 0x20,         # 0x66=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x14, 0x83,         # 0x67=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x20, 0xE6,         # 0x68=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x2D, 0x49,         # 0x69=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x39, 0xAC,         # 0x6A=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x46, 0x0F,         # 0x6B=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x04, 0x12,         # 0x6C=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x10, 0x62,         # 0x6D=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x1C, 0xC5,         # 0x6E=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x29, 0x28,         # 0x6F=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x35, 0x8B,         # 0x70=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x41, 0xEE,         # 0x71=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
            0x02, 0x51          # 0x72=0x0000 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
                                #        0x00 = 0(hex, delay 0:0us) ; 0x20 = 1(hex, delay 1:8us) ;
                                #        0x40 = 2(hex, delay 2:16us); 0x60 = 3(hex, delay 3:24us);
                                #        0x80 = 4(hex, delay 4:32us); 0xA0 = 5(hex, delay 5:40us);
                                #        0xC0 = 6(hex, delay 6:48us); 0xA0 = 7(hex, delay 7:56us);
        ]
delay.extend(filler)
set_delay = combine_hex_elements(delay, chunk_size)

# DEV_ID (0x00) Read
#Dev_ID = [0x3F, 0x81, 0x00]          # Broadast(Write with Same data) 1 address from 0x00(Dev_ID)
#Dev_ID.extend([0x00, 0x00] * 1 * 22) 
Dev_ID = [0x3F, 0x81, 0x00,   # Broadast(Read data) 1 address from 0x00(DEV_ID)
          0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
          0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
          0x00,0x00, 0x00,0x00, 0x00,0x00,
          0x00,0x40, 0x01,0x40, 0x02,0x40, 0x03,0x40,   # Dev# 1~ 4;
          0x04,0x40, 0x05,0x40, 0x06,0x40, 0x07,0x40,   # Dev# 5~ 8;
          0x08,0x40, 0x09,0x40, 0x0A,0x40, 0x0B,0x40,   # Dev# 9~12;
          0x0C,0x40, 0x0D,0x40, 0x0E,0x40, 0x0F,0x40,   # Dev#13~16;
          0x10,0x40, 0x11,0x40, 0x12,0x40, 0x13,0x40,   # Dev#17~20;
          0x14,0x40, 0x15,0x40                          # Dev#21~24;
         ]
#Dev_ID.extend(filler)
Dev_Ver = combine_hex_elements(Dev_ID, chunk_size)

def check_board_version(useful_data, device_count=22):
    # 各デバイスのデータから第2バイトのみを抽出(2バイトごとに1個スキップしながら)
    # 例:useful_data[1], useful_data[3], useful_data[5], ... と取り出す(合計device_count個)
    second_bytes = useful_data[1:device_count*2:2]
    Led_board_is_p2 = True                  # 最初は全デバイスが「P2ボード」と仮定
    for i, byte in enumerate(second_bytes): # second_bytes の中のすべてのデータを1つずつ取り出して、そのときの番号(index)も一緒に取り出すため
        bin_str = "{:08b}".format(byte)     # byte(整数)を8桁の2進数に変換(例:0x3A → "00111010")
        print(f"Device {i+1}: 0x{byte:02X} -> {bin_str}")

        bit7 = (byte >> 7) & 1
        bit6 = (byte >> 6) & 1
        bit5 = (byte >> 5) & 1
        version_bits = f"{bit7}{bit6}{bit5}"
        print(f"Device {i+1} version bits: {version_bits}")
        rev_id = (byte >> 5) & 7
        print(rev_id)

        if version_bits == "000":
            print(f"Critical error: Device {i+1} version bits is '000'. Aborting program.")
            raise SystemExit("Version bits '000' detected, aborting.")  # プログラムを終了

        if version_bits != "010":                                       # 「010」以外がある場合は、P2ボードではないと判断
            Led_board_is_p2 = False
            
    board_type = "P2" if Led_board_is_p2 else "Not P2"
    print(f"Board Type: {board_type}")
    
    return board_type                # 判定結果を返す

def get_board_type_from_raw(raw_data):
    split_data = split_rd_data(raw_data)
    useful_data = split_data[25:]
    print("MISO Response (filtered):", useful_data)
    board_type = check_board_version(useful_data)
    return board_type

# BIST_REG(R18h)
# Bist ON
BistOn = [0x3E, 0x01, 0x18,     # Broadast(Write with Same data) 1 address from 0x18(BIST_REG)
          0x00, 0x03]           # [2]BIST_CURR=0(10uA), [1]BIST_ODD=1(Enable), [0]BIST_EVEN=1(Enable)
BistOn.extend(filler)
BIST_ON = combine_hex_elements(BistOn, chunk_size)

BistOn_odd = [0x3E, 0x01, 0x18,   # Broadast(Write with Same data) 1 address from 0x18(BIST_REG)
              0x00, 0x02]         # [2]BIST_CURR=0(10uA), [1]BIST_ODD=1(Enable), [0]BIST_EVEN=0(disable)
BistOn_odd.extend(filler)
BIST_ON_odd = combine_hex_elements(BistOn_odd, chunk_size)

BistOn_even = [0x3E, 0x01, 0x18,   # Broadast(Write with Same data) 1 address from 0x18(BIST_REG)
               0x00, 0x01]         # [2]BIST_CURR=0(10uA), [1]BIST_ODD=0(disable), [0]BIST_EVEN=1(Enable)
BistOn_even.extend(filler)
BIST_ON_even = combine_hex_elements(BistOn_even, chunk_size)

# Bist OFF
BistOff = [0x3E, 0x01, 0x18,   # Broadast(Write with Same data) 1 address from 0x18(BIST_REG)
           0x00, 0x00]         # [2]BIST_CURR=0(10uA), [1]BIST_ODD=0(Disable), [0]BIST_EVEN=0(Disable)
BistOff.extend(filler)
BIST_OFF = combine_hex_elements(BistOff, chunk_size)

# BIST1_38(R19h~R1Bh) Read
BistRead = [0x3F, 0x83, 0x19]           # Broadast(Read with Different Data) 3 address from 0x19~0x1B(BIST1_38)
BistRead.extend([0x00, 0x00] * 3 * 22)  # 3 address 22 device
BistRead.extend(filler)
BIST_RD = combine_hex_elements(BistRead, chunk_size)

#EN 1(Switch Go)
en_1 = [0x3E, 0x01, 0x26,   # Broadast(Write with Same data) 13 address from 0x26(Switch Go)
        0x80, 0x00          # EN=1
       ]
en_1.extend(filler)
e1 = combine_hex_elements(en_1, chunk_size)

en_0 = [0x3E, 0x01, 0x26,   # Broadast(Write with Same data) 13 address from 0x26(Switch Go)
        0x00, 0x00          # EN=0
       ]
en_0.extend(filler)
e0 = combine_hex_elements(en_0, chunk_size)

def init_AOI_full_lighting():       # Initial settings configured to enable full lighting for AOI inspection.
    global board_type
    led_pin.value(1)
    Vddio.value(1)
    #Vddio_2.value(0)
    utime.sleep_ms(10)
    cs_pin.value(1)
    utime.sleep_ms(1)
    #pwm.duty_u16(int(65535 * 0.01))          # Send PWM signal, set duty cycle to 1%
    #utime.sleep_ms(20)
    Vled.value(1)
    utime.sleep_ms(1)

    pio_spi.write_blocking(res_data)          # Send reset_data
    utime.sleep_ms(10)
    pio_spi.write_blocking(enumeration_data)
    #pio_spi.write_read_blocking(Dev_Ver)
    #print(Dev_data)
    pio_spi.write_blocking(s23_25)
    #pio_spi.write_blocking(R29h_SLDET_1)        # ShortLED detect for BIST                                                                  
    pio_spi.write_blocking(s17)               # 5mA
    pio_spi.write_blocking(s14)
    pio_spi.write_blocking(s16)
    pio_spi.write_blocking(ILEDn)             # 84%=>  5mA*84%=4.2mA
    pio_spi.write_blocking(set_delay)
    pio_spi.write_blocking(GBL_PWM0)          # duty 0%
    #board_type = get_board_type_from_raw(raw_data)
  #  if global_board_type != "P2":
  #      print("Non-P2 board detected, terminating program.")
  #      raise SystemExit("Non-P2 board, exit.")
  #
  #  print("P2 board detected, running change_pwm_aligned_skip_lighting()")
  #  change_pwm_aligned_skip_lighting()

def judge_LED_board():
    global board_type
    led_pin.value(1)
    #Vddio.value(1)
    ##Vddio_2.value(0)
    #utime.sleep_ms(10)
    #cs_pin.value(1)
    #utime.sleep_ms(1)
    ##pwm.duty_u16(int(65535 * 0.01))          # Send PWM signal, set duty cycle to 1%
    ##utime.sleep_ms(20)
    #Vled.value(1)
    #utime.sleep_ms(1)

    #pio_spi.write_blocking(res_data)          # Send reset_data
    #utime.sleep_ms(10)
    #pio_spi.write_blocking(enumeration_data)
    #pio_spi.write_blocking(s23_25)
    #pio_spi.write_blocking(R29h_SLDET_1)        # ShortLED detect for BIST   
    raw_data = pio_spi.write_read_blocking(Dev_Ver)
    board_type = get_board_type_from_raw(raw_data)

    if board_type == "P2":
        print("P2 board detected - using aligned skip lighting")
        #change_pwm_aligned_skip_lighting()
        #pio_spi.write_blocking(e1)
        #print("Executing change_pwm_aligned_skip_lighting()")
        utime.sleep_ms(1000)
        #Bist_odd_2_5V()
        #print('odd LED pattern')
        #Bist_even_2_5V()
        #print('even LED pattern')
        #Bist_odd_2_0V()
        #print('odd LED pattern')
        #Bist_even_2_0V()
        #print('even LED pattern')
    else:
        print("Not P2 board")
        raise SystemExit("Only P2 boards supported.")
    #status = 0  # 状態を status = 0 にする

def Bist_testing():
    led_pin.value(1)
    Vddio.value(1)
    #Vddio_2.value(0)
    utime.sleep_ms(10)
    cs_pin.value(1)
    utime.sleep_ms(1)
    #pwm.duty_u16(int(65535 * 0.01))          # Send PWM signal, set duty cycle to 1%
    #utime.sleep_ms(20)
    Vled.value(1)
    utime.sleep_ms(1)

    pio_spi.write_blocking(res_data)          # Send reset_data
    utime.sleep_ms(10)
    pio_spi.write_blocking(enumeration_data)
    pio_spi.write_blocking(s23_25)
    pio_spi.write_blocking(R29h_SLDET_1)        # ShortLED detect for BIST   
    Bist_odd_2_5V()
    print('odd LED pattern')
    Bist_even_2_5V()
    print('even LED pattern')
#    Bist_odd_2_0V()
#    print('odd LED pattern')
#    Bist_even_2_0V()
#    print('even LED pattern')

# バイト列の中で「偶数位のビット」が1になっているビットの総数を数える
def count_even_bits(byte_list):
    count = 0                                            # カウンタ変数countを0で初期化。ここに合計値を蓄積
    for value in byte_list:                              # リストの中身を1つずつ取り出して処理するループ
        masked = value & 0b10101010                      # 「偶数位のビット」だけを取り出す。(左から第2,4,6,8位を数える)
        count += bin(masked)[2:].count('1')              # 整数を2進数の文字列に変えて、1の数を数えて、合計する
    return count                                         # 全部の value をチェックしたら、1の合計数(偶数位にある1の合計)をcountに返す

# バイト列の中で「奇数位のビット」が1になっているビットの総数を数える
def count_odd_bits(byte_list):
    count = 0                                            # カウンタ変数countを0で初期化。ここに合計値を蓄積
    for value in byte_list:                              # リストの中身を1つずつ取り出して処理するループ
        masked = value & 0b01010101                      # 「奇数位のビット」だけを取り出す。(右から第1,3,5,7位を数える)
        count += bin(masked)[2:].count('1')              # 整数を2進数の文字列に変えて、1の数を数えて、合計する
    return count                                         # 全部の value をチェックしたら、1の合計数(奇数位にある1の合計)をcountに返す
    print(count)

def split_rd_data(raw_data):
    # 各32ビットのデータを読み出し、4つの8ビットに分解し、1次元配列として展開します。
    rd_data = []                                         # 空のリストを用意して、デコードしたデータをここに格納します。
    for data in raw_data:                                # Bist_RD_data の各データ(1つずつ)に対して処理します。
        rd_data.extend([
            (data >> (8 * 3)) & (255),              # data を24ビット右シフト、最上位の8ビットを取り出す
            (data >> (8 * 2)) & (255),              # data を16ビット右シフトして、第2バイトを取り出す
            (data >> (8 * 1)) & (255),              # data を8ビット右シフトして、第1バイトを取り出す
            (data >> (8 * 0)) & (255)               # シフトなしで、そのまま最下位バイトを取り出す
        ])
    return rd_data                                       # 最終処理後の1次元配列を返します。その配列には、すべての8ビット値が格納されています。

def process_bist_data(raw_data, count_func):
    split_data = split_rd_data(raw_data)              # 上の関数でデコードする
    sliced_data = split_data[25:]                      # skip the 25 useless datas in the front
    return count_func(sliced_data)                       #点灯LEDの数を数える関数に渡す
EXPECTED_ODD_BIT_COUNT = 418
EXPECTED_EVEN_BIT_COUNT = 399

# Start up the BIST-Test(even_bit)
def Bist_even_2_5V():
    #pio_spi.write_blocking(res_data)          # Send reset_data
    #utime.sleep_ms(10)
    #pio_spi.write_blocking(enumeration_data)
    #pio_spi.write_blocking(s23_25)
    pio_spi.write_blocking(R29h_SLDET_1)        # ShortLED detect for BIST 

    pio_spi.write_blocking(BIST_ON_even)                                                      # 偶数番号のLEDにBIST信号を送って点灯させます。
    utime.sleep_ms(2500)                                                                        # LED点灯(10uA)確認→wait 500ms
    Bist_even_RD_data = pio_spi.write_read_blocking(BIST_RD)                                  # BIST Readコマンドを送信し、同時にLEDからの読み出しデータを受信します。
    #print(Bist_even_RD_data)
    even_bit_count_2_5V = process_bist_data(Bist_even_RD_data, count_even_bits)                    # count_even_bits 関数を使用して、返されるデータ Bist_even_RD_data を処理し、「偶数位置のLEDが点灯している数」をカウントします。
    print(even_bit_count_2_5V)

    if even_bit_count_2_5V > 0:
        print("LED board NG")
        sys.exit("LED灯板不合格")  # プログラムを終了
    else:
        print("LED board OK")

    #utime.sleep_ms(10)
    #for _ in range(50):  # 必要な回数だけ繰り返す
    #    Bist_even_RD_data = pio_spi.write_read_blocking(BIST_RD)
    #    even_bit_count = process_bist_data(Bist_even_RD_data, count_even_bits)                # count_even_bits 関数を使用して、返されるデータ Bist_even_RD_data を処理し、「偶数位置のLEDが点灯している数」をカウントします。
    #    print(even_bit_count)
    #    utime.sleep_ms(10)
    #print(f"[VF Check] Even pattern - total LEDs lit: {even_bit_count}")

   # if even_bit_count < EXPECTED_EVEN_BIT_COUNT:
   #     print("NG: One or more LEDs did NOT light up in even pattern!")
   #     raise SystemExit("BIST_even failure: Stop due to VF too high or disconnection.")
   # else:
   #     print("OK: All expected LEDs lit in BIST_even")

def Bist_odd_2_5V():
    #pio_spi.write_blocking(res_data)          # Send reset_data
    #utime.sleep_ms(10)
    #pio_spi.write_blocking(enumeration_data)
    #pio_spi.write_blocking(s23_25)
    pio_spi.write_blocking(R29h_SLDET_1)        # ShortLED detect for BIST 

    pio_spi.write_blocking(BIST_ON_odd)                                                       # SPI通信でコマンドをブロッキング送信、奇数番号のLEDにBIST信号を送って点灯させます。
    utime.sleep_ms(2500)                                                                        # LED点灯(10uA)確認→wait 500ms
    Bist_odd_RD_data = pio_spi.write_read_blocking(BIST_RD)                                   # BIST Readコマンドを送信し、同時にLEDからの読み出しデータを受信します。
    #print(Bist_odd_RD_data)
    odd_bit_count_2_5V = process_bist_data(Bist_odd_RD_data, count_odd_bits)                       # count_odd_bits 関数を使用して、返されるデータ Bist_odd_RD_data を処理し、「奇数位置のLEDが点灯している数」をカウントします。
    print(odd_bit_count_2_5V)

    if odd_bit_count_2_5V > 0:
        print("LED board NG")
        sys.exit("LED灯板不合格")  # プログラムを終了
    else:
        print("LED board OK")

    #utime.sleep_ms(10)
    #for _ in range(50):  # 必要な回数だけ繰り返す
    #    Bist_odd_RD_data = pio_spi.write_read_blocking(BIST_RD)
    #    odd_bit_count = process_bist_data(Bist_odd_RD_data, count_odd_bits)                   # count_odd_bits 関数を使用して、返されるデータ Bist_odd_RD_data を処理し、「奇数位置のLEDが点灯している数」をカウントします。
    #    print(odd_bit_count)
    #    utime.sleep_ms(10)
   # print(f"[VF Check] Odd pattern - total LEDs lit: {odd_bit_count}")
   # if odd_bit_count < EXPECTED_ODD_BIT_COUNT:
   #     print("NG: One or more LEDs did NOT light up in odd pattern!")
   #     raise SystemExit("BIST_odd failure: Stop due to VF too high or disconnection.")
   # else:
   #     print("OK: All expected LEDs lit in BIST_odd")

def Bist_even_2_0V():
    #pio_spi.write_blocking(res_data)          # Send reset_data
    #utime.sleep_ms(10)
    #pio_spi.write_blocking(enumeration_data)
    #pio_spi.write_blocking(s23_25)
    pio_spi.write_blocking(R29h_SLDET_2)        # ShortLED detect for BIST 

    pio_spi.write_blocking(BIST_ON_even)                                                      # 偶数番号のLEDにBIST信号を送って点灯させます。
    utime.sleep_ms(2500)                                                                        # LED点灯(10uA)確認→wait 500ms
    Bist_even_RD_data = pio_spi.write_read_blocking(BIST_RD)                                  # BIST Readコマンドを送信し、同時にLEDからの読み出しデータを受信します。
    #print(Bist_even_RD_data)
    even_bit_count_2_0V = process_bist_data(Bist_even_RD_data, count_even_bits)                    # count_even_bits 関数を使用して、返されるデータ Bist_even_RD_data を処理し、「偶数位置のLEDが点灯している数」をカウントします。
    print(even_bit_count_2_0V)
    
    if even_bit_count_2_0V < 399:
        print("LED board NG")
        sys.exit("LED灯板不合格")  # プログラムを終了
    else:
        print("LED board OK")

def Bist_odd_2_0V():
    #pio_spi.write_blocking(res_data)          # Send reset_data
    #utime.sleep_ms(10)
    #pio_spi.write_blocking(enumeration_data)
    #pio_spi.write_blocking(s23_25)
    pio_spi.write_blocking(R29h_SLDET_2)        # ShortLED detect for BIST 

    pio_spi.write_blocking(BIST_ON_odd)                                                       # SPI通信でコマンドをブロッキング送信、奇数番号のLEDにBIST信号を送って点灯させます。
    utime.sleep_ms(2500)                                                                        # LED点灯(10uA)確認→wait 500ms
    Bist_odd_RD_data = pio_spi.write_read_blocking(BIST_RD)                                   # BIST Readコマンドを送信し、同時にLEDからの読み出しデータを受信します。
    #print(Bist_odd_RD_data)
    odd_bit_count_2_0V = process_bist_data(Bist_odd_RD_data, count_odd_bits)                       # count_odd_bits 関数を使用して、返されるデータ Bist_odd_RD_data を処理し、「奇数位置のLEDが点灯している数」をカウントします。
    print(odd_bit_count_2_0V)
    if odd_bit_count_2_0V < 418:
        print("LED board NG")
        sys.exit("LED灯板不合格")  # プログラムを終了
    else:
        print("LED board OK")


def change_pwm_all_leds(duty):
    for ic in range(0x01, 0x17):                    # It generates from IC No.1(0x01) to IC No.22(0x16) (that is, decimal 1 to 22).
        write_blocking_pwm([ic, 0x26, 0x40], duty)  # It is the register address format for setting PWM.


def turn_on_backlight():
    led_pin.value(1)
    Vddio.value(1)
    utime.sleep_ms(10)
    cs_pin.value(1)
    utime.sleep_ms(1)
    pwm.duty_u16(int(65535 * 0.01))  # Send PWM signal, set duty cycle to 1%
    utime.sleep_ms(20)
    Vled.value(1)
    utime.sleep_ms(1)
    # Before sending combined_data_2, ensure CS remains high
    print("call_write_read_blocking_reset")
    pio_spi.write_blocking(res_data)  # Send reset_data
    utime.sleep_ms(10)
    print("call_write_blocking_enu")
    pio_spi.write_blocking(enumeration_data)
    print("call_write_read")
    devID = pio_spi.write_read_blocking(dev_id_data)
    print(devID)
    print("call_write_s23-25")
    pio_spi.write_read_blocking(s23_25)
    print("call_write_s17")
    pio_spi.write_read_blocking(s17)
    print("call_write_s14")
    pio_spi.write_read_blocking(s14)
    print("call_write_s16")
    pio_spi.write_read_blocking(s16)
    print("call_write_ILEDn")
    pio_spi.write_read_blocking(ILEDn)
#     pio_spi.write_blocking(GBL_PWM0) # Broadast(Write with Same data) 1 address from 0x74(GBL_PWM_LOW16_VWDPORT)
    print("call_write_e1")
    pio_spi.write_read_blocking(e1)

def change_pwm():
    write_blocking_pwm([0x01, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x02, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x03, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x04, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x04, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x04, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x04, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x05, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x06, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x07, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x08, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x09, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x0A, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x0B, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x0C, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x0D, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x0E, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x0F, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x10, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x11, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x12, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x13, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x14, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x15, 0x26, 0x40], duty_value)
    write_blocking_pwm([0x16, 0x26, 0x40], duty_value)

def turn_off_backlight():
    pio_spi.write_read_blocking(e0)
    utime.sleep_ms(100)
    Vled.value(0)
    pwm.duty_u16(0)  # Stop PWM signal

    utime.sleep_ms(t2_ms) #1ms
    #cs_low() # Set CS low
    cs_pin.value(0)
    utime.sleep_ms(t3_ms) #50ms  # the time from VLED low to VDD low (50ms)
    # Set Vddio low
    Vddio.value(0)


# Initialize PWM    
#pwm = PWM(Pin(9), freq=vsy_freq, duty_u16=0)
sw1_st = 0
status = 0
status_pin.value(status & 1)
key1_press_count = 0  # Reset counter after KEY2 released

while True:
    if falling_edge_flag:
        print("スイッチが押されました!")
        if KEY2.value() == 0:
            led_pin.value(1)
            judge_LED_board()
            Bist_testing()
            init_AOI_full_lighting()
            while KEY2.value() == 0:
                utime.sleep_ms(10)

                if KEY1.value() == 0:
                    while KEY1.value() == 0:
                        utime.sleep_ms(1)
                    key1_press_count += 1

                    if key1_press_count == 1:
                        pwm = PWM(Pin(9), freq=vsy_freq, duty_u16=0)
                        pwm.duty_u16(int(65535 * 0.01))
                        utime.sleep_ms(20)
                        pio_spi.write_blocking(e1)
                        change_pwm_all_leds(duty_value_1)
                        print('Mode 1: all LED on with duty_value_1')
                        status = 1  # 状態を status = 1 にする

                    elif key1_press_count == 2:
                        pio_spi.write_blocking(e1)
                        change_pwm_all_leds(duty_value_2)
                        print('Mode 2: all LED on with duty_value_2')
                        status = 2  # 状態を status = 2 にする

    if rising_edge_flag:
        print("スイッチが離されました!")
        if KEY2.value() == 1:
            pwm = PWM(Pin(9), freq=vsy_freq, duty_u16=0)
            turn_off_backlight()
            led_pin.value(0)
            print('all LEDs off')
            key1_press_count = 0
#            break  # exit 【while KEY2 】 loop

#        while KEY2.value() == 0:  #  KEY2がちゃんと戻るのを待つ
#            utime.sleep_ms(10)

        status = 3                # 状態をstatus = 3 にする

    utime.sleep_ms(100)
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT