Compare commits
57 Commits
master
...
external-h
| Author | SHA1 | Date | |
|---|---|---|---|
| f7f5a16d64 | |||
| 5e12e9a4a0 | |||
| 65ac37fd62 | |||
| 364e62f933 | |||
| f0dfc95910 | |||
| 7aa3e0c3e5 | |||
| 14a33963b0 | |||
| ba23e42050 | |||
| 246183e9a3 | |||
| 7cf89e9e45 | |||
| 4ffb554d43 | |||
| adcf08f236 | |||
| 2ccf069e15 | |||
| 48f1656540 | |||
| f5dfa7960b | |||
| de32bd245c | |||
| 5828ecfb48 | |||
| 8adfe875cd | |||
| a38c71674b | |||
| 1fdf6d2cca | |||
| 7b1be30a6c | |||
| 0023394615 | |||
| 2a38ba36b0 | |||
| 4820010ef1 | |||
| a1590577d2 | |||
| 2c82d8d42e | |||
| 1ba352af4e | |||
| ab5e54a9dd | |||
| 77701636b5 | |||
| 55bee1a5d8 | |||
| 4591e6e04a | |||
| dae0fbcbda | |||
| 9e254e0fb1 | |||
| 90a94a533b | |||
| e1528385c2 | |||
| a75570e67b | |||
| 043fbba67e | |||
| 6bc4087474 | |||
| 821380d21c | |||
| 03bf92f505 | |||
| 5a6488535d | |||
| 920d0a46c3 | |||
| a51793e529 | |||
| 6cd3815d5a | |||
| 887f05a8ec | |||
| 4ad28fe1f5 | |||
| 686724770c | |||
| d79565b10d | |||
| ab1063aa27 | |||
| d8e14fb3a2 | |||
| 513d5e2f1f | |||
| 868bf18b0b | |||
| 8d16bdf96e | |||
| 9fc3f98d84 | |||
| 9605d1db0e | |||
| 6007b5d9e2 | |||
| 11e71d7539 |
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "fw/ch32fun"]
|
||||
path = fw/ch32fun
|
||||
url = https://github.com/cnlohr/ch32fun
|
||||
[submodule "fw/u8g2"]
|
||||
path = fw/u8g2
|
||||
url = https://github.com/olikraus/u8g2
|
||||
BIN
3D/3DModel.FCStd
BIN
3D/3DModel.FCStd
Binary file not shown.
BIN
3D/board_outline_v2.FCStd
Normal file
BIN
3D/board_outline_v2.FCStd
Normal file
Binary file not shown.
BIN
3D/extenal-handle/Enclosure.FCStd
Normal file
BIN
3D/extenal-handle/Enclosure.FCStd
Normal file
Binary file not shown.
BIN
3D/extenal-handle/External-Handle-Assembly.FCStd
Normal file
BIN
3D/extenal-handle/External-Handle-Assembly.FCStd
Normal file
Binary file not shown.
245995
3D/extenal-handle/I2C_OLED.step
Normal file
245995
3D/extenal-handle/I2C_OLED.step
Normal file
File diff suppressed because it is too large
Load Diff
8783
3D/extenal-handle/RPC1-12RB-6P.step
Normal file
8783
3D/extenal-handle/RPC1-12RB-6P.step
Normal file
File diff suppressed because it is too large
Load Diff
1519
3D/extenal-handle/export/Enclosure-Cap.step
Normal file
1519
3D/extenal-handle/export/Enclosure-Cap.step
Normal file
File diff suppressed because it is too large
Load Diff
1521
3D/extenal-handle/export/Enclosure-Shell.step
Normal file
1521
3D/extenal-handle/export/Enclosure-Shell.step
Normal file
File diff suppressed because it is too large
Load Diff
177258
3D/extenal-handle/main_pcb.step
Normal file
177258
3D/extenal-handle/main_pcb.step
Normal file
File diff suppressed because it is too large
Load Diff
BIN
3D/extenal-handle/usbc_soldering_iron.FCStd
Normal file
BIN
3D/extenal-handle/usbc_soldering_iron.FCStd
Normal file
Binary file not shown.
12
README.md
12
README.md
@ -2,4 +2,14 @@
|
||||
|
||||
Repo for a cool usb-c soldering iron that uses C245 cartridges and power up to 130W.
|
||||
|
||||
Read the [project report](doc/report/README.md) (in italian).
|
||||
Read the [project report](doc/report/README.md) (in italian).
|
||||
|
||||
# IDEAS
|
||||
|
||||
* USB-C connector on the edge of the PCB like the [alientek T90B](https://youtu.be/Xl0IKpvlF3Y?si=ecKIGLwI0vSPZbJ4&t=7) (clamping plate)
|
||||
* OLED Screen on a separate PCB, same project with a V-Cut
|
||||
* More compact tip recess, stabilized by a, aluminium ring, maybe bought at the hardware store
|
||||
* Single screw disassembly
|
||||
* 13mm grip dimensions and 18mm otherwise
|
||||
* 1mm walls in PETG
|
||||
* Add a ~small~ button to the bootsel line
|
||||
|
||||
12
fw/.gitignore
vendored
Normal file
12
fw/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
.zen
|
||||
.vscode
|
||||
.ccls-cache
|
||||
.cache
|
||||
*.bin
|
||||
*.lst
|
||||
*.map
|
||||
*.elf
|
||||
*.hex
|
||||
*.o
|
||||
.build
|
||||
compile_commands.json
|
||||
BIN
fw/CH32X035DS0.pdf
Normal file
BIN
fw/CH32X035DS0.pdf
Normal file
Binary file not shown.
BIN
fw/CH32X035RM.pdf
Normal file
BIN
fw/CH32X035RM.pdf
Normal file
Binary file not shown.
46
fw/Makefile
Normal file
46
fw/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
all : build
|
||||
|
||||
TARGET := main
|
||||
TARGET_MCU := CH32X035
|
||||
TARGET_MCU_PACKAGE := CH32X035F8U6
|
||||
BUILD_DIR := .build
|
||||
DISPLAY := ssd1312
|
||||
|
||||
# include u8g2
|
||||
U8G2_DIR:=u8g2/csrc
|
||||
U8G2_SRC:=$(U8G2_DIR)/u8x8_d_$(DISPLAY).c $(filter-out $(U8G2_DIR)/u8x8_d_%.c, \
|
||||
$(filter-out $(U8G2_DIR)/mui%.c, $(wildcard $(U8G2_DIR)/*.c)))
|
||||
|
||||
EXTRA_CFLAGS += -I$(U8G2_DIR)
|
||||
ADDITIONAL_C_FILES += lib_i2c.c display.c sc7a20.c pd.c
|
||||
HEADER_FILES := $(wildcard *.h)
|
||||
|
||||
include ch32fun/ch32fun/ch32fun.mk
|
||||
|
||||
FLASH_COMMAND=$(MINICHLINK)/minichlink -C isp -w $< $(WRITE_SECTION) -b
|
||||
|
||||
# create build directory
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
# build u8g2
|
||||
U8G2_OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(U8G2_SRC:.c=.o)))
|
||||
$(BUILD_DIR)/%.o : $(U8G2_DIR)/%.c | $(BUILD_DIR)
|
||||
$(PREFIX)-gcc $(CFLAGS) -c $< -o $@
|
||||
|
||||
# build target
|
||||
TARGET_OBJS := $(addprefix $(BUILD_DIR)/, $(filter-out ch32fun.o, $(notdir $(FILES_TO_COMPILE:.c=.o))))
|
||||
$(BUILD_DIR)/%.o : %.c $(HEADER_FILES) | $(BUILD_DIR)
|
||||
$(PREFIX)-gcc $(CFLAGS) -c $< -o $@
|
||||
|
||||
# link target, the rest of the build is specified in ch32fun.mk
|
||||
$(TARGET).elf : $(FILES_TO_COMPILE) $(LINKER_SCRIPT) $(EXTRA_ELF_DEPENDENCIES) $(U8G2_OBJS) $(TARGET_OBJS) ch32fun.o
|
||||
$(PREFIX)-gcc -o $@ $(U8G2_OBJS) $(TARGET_OBJS) ch32fun.o $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
|
||||
flash : cv_flash
|
||||
clean : cv_clean
|
||||
rm -f $(BUILD_DIR)/*.o *.o || true
|
||||
|
||||
monitor :
|
||||
picocom --imap lfcrlf /dev/ttyACM0
|
||||
1
fw/ch32fun
Submodule
1
fw/ch32fun
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cfffff6d6bd9bd97d7348d044a1de145f4548072
|
||||
177
fw/display.c
Normal file
177
fw/display.c
Normal file
@ -0,0 +1,177 @@
|
||||
#include <u8g2.h>
|
||||
#include <ch32fun.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "lib_i2c.h"
|
||||
|
||||
|
||||
/*
|
||||
* GPIO and delay callback for u8g2/u8x8 display driver
|
||||
*/
|
||||
|
||||
|
||||
static u8g2_t u8g2;
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg) {
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
// called once during init phase of u8g2/u8x8
|
||||
// can be used to setup pins
|
||||
printf("TODO: U8X8_MSG_GPIO_AND_DELAY_INIT\n");
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
// delay arg_int * 1 nano second
|
||||
// at 48MHz 1 cycle = 20ns, 1 nop = 1 cycle
|
||||
// the for lopp takes about 2 cycles per iteration
|
||||
for (int i = 0; i < (arg_int/(20*3)); i++) {
|
||||
asm("nop");
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
// delay arg_int * 100 nano seconds
|
||||
// at 48MHz 1 cycle = 20ns, 1 nop = 1 cycle
|
||||
// the for lopp takes about 2 cycles per iteration
|
||||
for (int i = 0; i < ((arg_int*100)/(20*3)); i++) {
|
||||
asm("nop");
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
// delay arg_int * 10 micro seconds
|
||||
Delay_Us(arg_int*10);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
// delay arg_int * 1 milli second
|
||||
Delay_Ms(arg_int);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
// arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
|
||||
// arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
|
||||
printf("TODO: U8X8_MSG_DELAY_I2C\n");
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D0:
|
||||
// D0 or SPI clock pin: Output level in arg_int
|
||||
//case U8X8_MSG_GPIO_SPI_CLOCK:
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D1:
|
||||
// D1 or SPI data pin: Output level in arg_int
|
||||
//case U8X8_MSG_GPIO_SPI_DATA:
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D2:
|
||||
// D2 pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D3:
|
||||
// D3 pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D4:
|
||||
// D4 pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D5:
|
||||
// D5 pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D6:
|
||||
// D6 pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_D7:
|
||||
// D7 pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_E:
|
||||
// E/WR pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_CS:
|
||||
// CS (chip select) pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_DC:
|
||||
// DC (data/cmd, A0, register select) pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_RESET:
|
||||
funDigitalWrite(PIN_DISP_RST, arg_int);
|
||||
// Reset pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_CS1:
|
||||
// CS1 (chip select) pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_CS2:
|
||||
// CS2 (chip select) pin: Output level in arg_int
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
// arg_int=0: Output low at I2C clock pin
|
||||
// arg_int=1: Input dir with pullup high for I2C clock pin
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
// arg_int=0: Output low at I2C data pin
|
||||
// arg_int=1: Input dir with pullup high for I2C data pin
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
// get menu select pin state
|
||||
u8x8_SetGPIOResult(u8x8, 0);
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
// get menu next pin state
|
||||
u8x8_SetGPIOResult(u8x8, 0);
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
// get menu prev pin state
|
||||
u8x8_SetGPIOResult(u8x8, 0);
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
// get menu home pin state
|
||||
u8x8_SetGPIOResult(u8x8, 0);
|
||||
break;
|
||||
default:
|
||||
// default return value
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_byte_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
static uint8_t buffer[32];
|
||||
static uint8_t buffer_idx;
|
||||
uint8_t *data;
|
||||
|
||||
switch(msg) {
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t*)arg_ptr;
|
||||
while (arg_int > 0) {
|
||||
buffer[buffer_idx++] = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
buffer_idx = 0;
|
||||
break;
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
i2c_sendBytes(I2C_TARGET, u8x8_GetI2CAddress(u8x8) >> 1, buffer, buffer_idx);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
u8g2_t* display_init(void)
|
||||
{
|
||||
#if defined(SSD1306_128X32) && SSD1306_128X32
|
||||
u8g2_Setup_ssd1306_i2c_128x32_univision_f(&u8g2, U8G2_R0, u8x8_byte_i2c, u8x8_gpio_and_delay);
|
||||
#elif defined(SSD1312_96X16) && SSD1312_96X16
|
||||
// NOTE: display size is wrong, hardware is 96x16, but driver is configured for 120x28
|
||||
u8g2_Setup_ssd1312_i2c_128x32_f(&u8g2, U8G2_R0, u8x8_byte_i2c, u8x8_gpio_and_delay);
|
||||
#else
|
||||
static_assert(0, "unsupported display size");
|
||||
#endif
|
||||
// TODO: log errors and return NULL on failure
|
||||
u8g2_InitDisplay(&u8g2);
|
||||
u8g2_SetPowerSave(&u8g2, 0);
|
||||
u8g2_SetContrast(&u8g2, 255);
|
||||
return &u8g2;
|
||||
}
|
||||
12
fw/display.h
Normal file
12
fw/display.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _DISPLAY_H
|
||||
#define _DISPLAY_H
|
||||
|
||||
#include <u8g2.h>
|
||||
|
||||
// #define SSD1306_128X32 1
|
||||
#define SSD1312_96X16 1
|
||||
#define PIN_DISP_RST PA7 // display reset
|
||||
|
||||
u8g2_t* display_init(void);
|
||||
|
||||
#endif // _DISPLAY_H
|
||||
20
fw/filter.h
Normal file
20
fw/filter.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _FILTER_H
|
||||
#define _FILTER_H
|
||||
|
||||
|
||||
// Fixed-Point Exponential Moving Average
|
||||
// alpha = 1/2^k
|
||||
// x: output value
|
||||
// s: current sample
|
||||
#define U16_FP_EMA_K2(x, s) (u16)((((u32)(x)<<2) - (x) + (s)) >> 2)
|
||||
#define U16_FP_EMA_K4(x, s) (u16)((((u32)(x)<<4) - (x) + (s)) >> 4)
|
||||
#define U16_FP_EMA_K8(x, s) (u16)((((u32)(x)<<8) - (x) + (s)) >> 8)
|
||||
#define U16_FP_EMA_K16(x, s) (u16)((((u32)(x)<<16) - (x) + (s)) >> 16)
|
||||
|
||||
#define I16_FP_EMA_K2(x, s) (s16)((((s32)(x)<<2) - (x) + (s)) >> 2)
|
||||
#define I16_FP_EMA_K4(x, s) (s16)((((s32)(x)<<4) - (x) + (s)) >> 4)
|
||||
#define I16_FP_EMA_K8(x, s) (s16)((((s32)(x)<<8) - (x) + (s)) >> 8)
|
||||
#define I16_FP_EMA_K16(x, s) (s16)((((s32)(x)<<16) - (x) + (s)) >> 16)
|
||||
|
||||
|
||||
#endif // _FILTER_H
|
||||
45
fw/funconfig.h
Normal file
45
fw/funconfig.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef _FUNCONFIG_H
|
||||
#define _FUNCONFIG_H
|
||||
|
||||
#define FUNCONF_USE_DEBUGPRINTF 0 // can only have one printf
|
||||
#define FUNCONF_USE_USBPRINTF 1
|
||||
#define FUNCONF_DEBUG_HARDFAULT 0
|
||||
#define CH32X035 1
|
||||
#define I2C_TARGET I2C1
|
||||
#define VCC_MV 3480
|
||||
#define FRAME_TIME_MS 20 // 50Hz
|
||||
#define PWM_FREQ_HZ 100000 // TIM3 PWM frequency
|
||||
|
||||
// Pin definitions
|
||||
#define PIN_VBUS PA0 // vbus voltage feedback
|
||||
#define PIN_CURRENT PA1 // current feedback
|
||||
#define PIN_NTC PA2 // ntc temperature sensor
|
||||
#define PIN_TEMP PA3 // thermocouple amplifier
|
||||
#define PIN_12V PA5 // 12V regulator enable
|
||||
#define PIN_HEATER PA6 // power mosfet gate control
|
||||
#define PIN_ENC_A PB3 // rotary encoder A
|
||||
#define PIN_ENC_B PB11 // rotary encoder B
|
||||
#define PIN_BTN PB1 // rotary encoder button
|
||||
|
||||
// Analog channel definitions
|
||||
#define VBUS_ADC_CHANNEL ANALOG_0 // PA0
|
||||
#define CURRENT_ADC_CHANNEL ANALOG_1 // PA1
|
||||
#define NTC_ADC_CHANNEL ANALOG_2 // PA2
|
||||
#define TEMP_ADC_CHANNEL ANALOG_3 // PA3
|
||||
|
||||
#define ENCODER_DEBOUNCE 6000
|
||||
|
||||
// TODO: these need to be calibrated
|
||||
// Tip mV to deg C conversion factor numerator
|
||||
#define TC_CONV_NOM 151
|
||||
// Tip mV to deg C conversion factor denumerator
|
||||
#define TC_CONV_DEN 1000
|
||||
|
||||
#define MAX_BOARD_TEMP 50
|
||||
#define MAX_TIP_TEMP 500
|
||||
#define TURN_OFF_DELAY 2
|
||||
#define CYCLES_PER_MEASURE 2
|
||||
#define BOARD_MAX_VOLTAGE 28000
|
||||
|
||||
|
||||
#endif // _FUNCONFIG_H
|
||||
231
fw/lib_i2c.c
Normal file
231
fw/lib_i2c.c
Normal file
@ -0,0 +1,231 @@
|
||||
// MIT License
|
||||
// Copyright (c) 2025 UniTheCat
|
||||
// Tested with Ch32X03x and CH32V30x
|
||||
|
||||
#include "lib_i2c.h"
|
||||
|
||||
|
||||
//! ####################################
|
||||
//! I2C INIT FUNCTIONS
|
||||
//! ####################################
|
||||
|
||||
void i2c_init(I2C_TypeDef* I2Cx, u32 PCLK, u32 i2cSpeed_Hz) {
|
||||
// Enable I2C clock
|
||||
if (I2Cx == I2C1) {
|
||||
RCC->APB1PCENR |= RCC_APB1Periph_I2C1;
|
||||
}
|
||||
#ifdef I2C2
|
||||
else if (I2Cx == I2C2) {
|
||||
RCC->APB1PCENR |= RCC_APB1Periph_I2C2;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Disable I2C before configuration
|
||||
I2Cx->CTLR1 &= ~I2C_CTLR1_PE;
|
||||
|
||||
// configure I2C clock
|
||||
I2Cx->CTLR2 = (PCLK / 1000000);
|
||||
I2Cx->CKCFGR = PCLK / (i2cSpeed_Hz << 1); // PeripheralClock / (100KHz * 2)
|
||||
|
||||
// Enable I2C
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_PE;
|
||||
|
||||
// Enable ACK
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_ACK;
|
||||
}
|
||||
|
||||
u8 i2c_start(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 isRead) {
|
||||
//# Wait while BUSY, when BUSY is set to 0 then continue
|
||||
u32 timeout = I2C_DEFAULT_TIMEOUT;
|
||||
while((I2Cx->STAR2 & I2C_STAR2_BUSY) && --timeout);
|
||||
// if (timeout == 0) { I2Cx->CTLR1 |= I2C_CTLR1_STOP; return 0x11; }
|
||||
|
||||
//# Generate START condition
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_START;
|
||||
|
||||
//# Wait while SB is 0, when SB is set to 1 then continue
|
||||
timeout = I2C_DEFAULT_TIMEOUT;
|
||||
while(!(I2Cx->STAR1 & I2C_STAR1_SB) && --timeout);
|
||||
if (timeout == 0) { I2Cx->CTLR1 |= I2C_CTLR1_STOP; return 0x12; }
|
||||
// printf("timeoutB: %d\n", I2C_DEFAULT_TIMEOUT - timeout);
|
||||
|
||||
//# Send address + read/write. Write = 0, Read = 1
|
||||
I2Cx->DATAR = (i2cAddress << 1) | isRead;
|
||||
|
||||
//# Wait while ADDR is 0, if ADDR is set to 1 then continue
|
||||
timeout = I2C_DEFAULT_TIMEOUT;
|
||||
while(!(I2Cx->STAR1 & I2C_STAR1_ADDR) && --timeout);
|
||||
if (timeout == 0) { I2Cx->CTLR1 |= I2C_CTLR1_STOP; return 0x13; }
|
||||
// printf("timeoutC: %d\n", I2C_DEFAULT_TIMEOUT - timeout);
|
||||
|
||||
//! REQUIRED. Clear ADDR by reading STAR1 then STAR2
|
||||
(void)I2Cx->STAR1;
|
||||
(void)I2Cx->STAR2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_stop(I2C_TypeDef* I2Cx)
|
||||
{
|
||||
//# Generate STOP condition
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_STOP;
|
||||
}
|
||||
|
||||
void i2c_scan(I2C_TypeDef* I2Cx, void (*onPingFound)(u8 address)) {
|
||||
// mininum 0x08 to 0x77 (0b1110111)
|
||||
for (int i = 0x08; i < 0x77; i++) {
|
||||
u8 ping = i2c_start(I2Cx, i, 1);
|
||||
|
||||
//# Generate STOP condition
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_STOP;
|
||||
if (ping == 0) onPingFound(i);
|
||||
}
|
||||
}
|
||||
|
||||
//! ####################################
|
||||
//! I2C SEND FUNCTION
|
||||
//! ####################################
|
||||
|
||||
u8 i2c_sendBytes_noStop(I2C_TypeDef* I2Cx, u8 i2cAddress, const u8* buffer, u8 len) {
|
||||
u8 err = i2c_start(I2Cx, i2cAddress, 0); // Write mode
|
||||
if (err) return err;
|
||||
u32 timeout;
|
||||
|
||||
for(u8 i = 0; i < len; i++) {
|
||||
//# Wait for register empty
|
||||
timeout = I2C_DEFAULT_TIMEOUT;
|
||||
while(!(I2Cx->STAR1 & I2C_STAR1_TXE) && --timeout);
|
||||
if (timeout == 0) { I2Cx->CTLR1 |= I2C_CTLR1_STOP; return 0x21; }
|
||||
I2Cx->DATAR = buffer[i]; // Send data
|
||||
}
|
||||
|
||||
//# Wait for transmission complete. Wait while BTF is 0, when set to 1 continue
|
||||
timeout = I2C_DEFAULT_TIMEOUT;
|
||||
while(!(I2Cx->STAR1 & I2C_STAR1_BTF) && --timeout);
|
||||
if (timeout == 0) { I2Cx->CTLR1 |= I2C_CTLR1_STOP; return 0x22; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 i2c_sendBytes(I2C_TypeDef* I2Cx, u8 i2cAddress, const u8* buffer, u8 len) {
|
||||
u8 err = i2c_sendBytes_noStop(I2Cx, i2cAddress, buffer, len);
|
||||
//# Generate STOP condition
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_STOP;
|
||||
return err;
|
||||
}
|
||||
|
||||
u8 i2c_sendByte(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 data) {
|
||||
return i2c_sendBytes(I2Cx, i2cAddress, &data, 1);
|
||||
}
|
||||
|
||||
|
||||
//! ####################################
|
||||
//! I2C RECEIVE FUNCTIONS
|
||||
//! ####################################
|
||||
|
||||
u8 i2c_readBytes(I2C_TypeDef* I2Cx, u8 i2cAddress, u8* buffer, u8 len) {
|
||||
u8 err = i2c_start(I2Cx, i2cAddress, 1); // Read mode
|
||||
if (err) return err;
|
||||
|
||||
//# Enable ACK at the beginning
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_ACK;
|
||||
|
||||
for(u8 i = 0; i < len; i++) {
|
||||
//# Before reading the last bytes, disable ACK to signal the slave to stop sending
|
||||
if(i == len-1) I2Cx->CTLR1 &= ~I2C_CTLR1_ACK;
|
||||
|
||||
//# Wait for data. Wait while RxNE is 0, when set to 1 continue
|
||||
u32 timeout = I2C_DEFAULT_TIMEOUT;
|
||||
while(!(I2Cx->STAR1 & I2C_STAR1_RXNE) && --timeout);
|
||||
if (timeout == 0) { I2Cx->CTLR1 |= I2C_CTLR1_STOP; return 0x31; }
|
||||
|
||||
//# Read data
|
||||
buffer[i] = I2Cx->DATAR;
|
||||
}
|
||||
|
||||
//# Generate STOP condition
|
||||
I2Cx->CTLR1 |= I2C_CTLR1_STOP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write to register and then do read data, no stop inbetween
|
||||
u8 i2c_readRegTx_buffer(I2C_TypeDef* I2Cx, u8 i2cAddress,
|
||||
u8 *tx_buf, u8 tx_len, u8 *rx_buf, u8 rx_len
|
||||
) {
|
||||
u8 err = i2c_sendBytes_noStop(I2Cx, i2cAddress, tx_buf, tx_len); // Send register address
|
||||
if (err) return err;
|
||||
err = i2c_readBytes(I2Cx, i2cAddress, rx_buf, rx_len); // Read data
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
//! ####################################
|
||||
//! I2C SLAVE FUNCTIONS
|
||||
//! ####################################
|
||||
|
||||
void i2c_slave_init(I2C_TypeDef* I2Cx, u16 self_addr, u32 PCLK, u32 i2cSpeed_Hz) {
|
||||
i2c_init(I2Cx, PCLK, i2cSpeed_Hz);
|
||||
|
||||
// Configure the CH32 I2C slave address to make it an I2C slave
|
||||
I2Cx->OADDR1 = (self_addr << 1);
|
||||
I2Cx->OADDR2 = 0;
|
||||
|
||||
I2Cx->CTLR2 |= I2C_CTLR2_ITEVTEN | I2C_CTLR2_ITERREN | I2C_CTLR2_ITBUFEN;
|
||||
|
||||
// Enable Event and Error Interrupts
|
||||
if (I2Cx == I2C1) {
|
||||
NVIC_EnableIRQ(I2C1_EV_IRQn); // I2C Event interrupt
|
||||
NVIC_EnableIRQ(I2C1_ER_IRQn); // I2C Error interrupt
|
||||
}
|
||||
|
||||
#ifdef I2C2
|
||||
else if (I2Cx == I2C2) {
|
||||
NVIC_EnableIRQ(I2C2_EV_IRQn); // I2C Event interrupt
|
||||
NVIC_EnableIRQ(I2C2_ER_IRQn); // I2C Error interrupt
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void I2C1_ER_IRQHandler(void) __attribute__((interrupt));
|
||||
void I2C1_ER_IRQHandler(void) {
|
||||
// get I2C status
|
||||
uint16_t STAR1 = I2C1->STAR1;
|
||||
|
||||
// Obtain and clear Bus error
|
||||
if (STAR1 & I2C_STAR1_BERR) {
|
||||
I2C1->STAR1 &= ~(I2C_STAR1_BERR);
|
||||
}
|
||||
|
||||
// Obtain and clear Arbitration lost error
|
||||
if (STAR1 & I2C_STAR1_ARLO) {
|
||||
I2C1->STAR1 &= ~(I2C_STAR1_ARLO);
|
||||
}
|
||||
|
||||
// Obtain and clear Acknowledge failure error
|
||||
if (STAR1 & I2C_STAR1_AF) {
|
||||
I2C1->STAR1 &= ~(I2C_STAR1_AF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef I2C2
|
||||
void I2C2_ER_IRQHandler(void) __attribute__((interrupt));
|
||||
void I2C2_ER_IRQHandler(void) {
|
||||
// get I2C status
|
||||
uint16_t STAR1 = I2C2->STAR1;
|
||||
|
||||
// Obtain and clear Bus error
|
||||
if (STAR1 & I2C_STAR1_BERR) {
|
||||
I2C2->STAR1 &= ~(I2C_STAR1_BERR);
|
||||
}
|
||||
|
||||
// Obtain and clear Arbitration lost error
|
||||
if (STAR1 & I2C_STAR1_ARLO) {
|
||||
I2C2->STAR1 &= ~(I2C_STAR1_ARLO);
|
||||
}
|
||||
|
||||
// Obtain and clear Acknowledge failure error
|
||||
if (STAR1 & I2C_STAR1_AF) {
|
||||
I2C2->STAR1 &= ~(I2C_STAR1_AF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
51
fw/lib_i2c.h
Normal file
51
fw/lib_i2c.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef _LIB_I2C_H
|
||||
#define _LIB_I2C_H
|
||||
|
||||
// MIT License
|
||||
// Copyright (c) 2025 UniTheCat
|
||||
// Tested with Ch32X03x and CH32V30x
|
||||
|
||||
#include <ch32fun.h>
|
||||
|
||||
|
||||
#define I2C_DEFAULT_TIMEOUT 50000
|
||||
|
||||
//! ####################################
|
||||
//! I2C INIT FUNCTIONS
|
||||
//! ####################################
|
||||
|
||||
void i2c_init(I2C_TypeDef* I2Cx, u32 PCLK, u32 i2cSpeed_Hz);
|
||||
u8 i2c_start(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 isRead);
|
||||
void i2c_stop(I2C_TypeDef* I2Cx);
|
||||
void i2c_scan(I2C_TypeDef* I2Cx, void (*onPingFound)(u8 address));
|
||||
|
||||
//! ####################################
|
||||
//! I2C SEND FUNCTION
|
||||
//! ####################################
|
||||
|
||||
u8 i2c_sendBytes_noStop(I2C_TypeDef* I2Cx, u8 i2cAddress, const u8* buffer, u8 len);
|
||||
u8 i2c_sendBytes(I2C_TypeDef* I2Cx, u8 i2cAddress, const u8* buffer, u8 len);
|
||||
u8 i2c_sendByte(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 data);
|
||||
|
||||
//! ####################################
|
||||
//! I2C RECEIVE FUNCTIONS
|
||||
//! ####################################
|
||||
|
||||
u8 i2c_readBytes(I2C_TypeDef* I2Cx, u8 i2cAddress, u8* buffer, u8 len);
|
||||
u8 i2c_readByte(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 reg, u8* buffer);
|
||||
|
||||
// Write to register and then do read data, no stop inbetween
|
||||
u8 i2c_readRegTx_buffer(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 *tx_buf, u8 tx_len, u8 *rx_buf, u8 rx_len);
|
||||
inline u8 i2c_readReg_buffer(I2C_TypeDef* I2Cx, u8 i2cAddress, u8 reg, u8 *rx_buf, u8 rx_len)
|
||||
{
|
||||
return i2c_readRegTx_buffer(I2Cx, i2cAddress, ®, 1, rx_buf, rx_len);
|
||||
}
|
||||
|
||||
//! ####################################
|
||||
//! I2C SLAVE FUNCTIONS
|
||||
//! ####################################
|
||||
|
||||
void i2c_slave_init(I2C_TypeDef* I2Cx, u16 self_addr, u32 PCLK, u32 i2cSpeed_Hz);
|
||||
|
||||
|
||||
#endif // _LIB_I2C_H
|
||||
22
fw/lincal.h
Normal file
22
fw/lincal.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef _LINCAL_H
|
||||
#define _LINCAL_H
|
||||
|
||||
#include <ch32fun.h>
|
||||
|
||||
|
||||
// Fixed-point number in 8.8 format
|
||||
typedef int16_t fp16_t;
|
||||
#define F32_TO_FP16(f) ((fp16_t)((f) * 256.0f))
|
||||
|
||||
// Intger part of fp16_t
|
||||
#define I(f) ((f) >> 8)
|
||||
// Decimal part of fp16_t
|
||||
#define D(f) ((f) & 0xFF)
|
||||
|
||||
// v * a + b for signed 16-bit
|
||||
#define I16_LINCAL(v, a, b) ((int16_t)((((int32_t)(v) * (a)) >> 8) + (b)))
|
||||
// v * a + b for unsigned 16-bit
|
||||
#define U16_LINCAL(v, a, b) ((uint16_t)((((uint32_t)(v) * (a)) >> 8) + (b)))
|
||||
|
||||
|
||||
#endif
|
||||
612
fw/main.c
Normal file
612
fw/main.c
Normal file
@ -0,0 +1,612 @@
|
||||
#include <ch32fun.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <fsusb.h>
|
||||
|
||||
#include "funconfig.h"
|
||||
#include "lib_i2c.h"
|
||||
#include "display.h"
|
||||
#include "filter.h"
|
||||
#include "sc7a20.h"
|
||||
#include "pd.h"
|
||||
|
||||
|
||||
// constants
|
||||
// LUT for converting NTC readings to degrees celsius
|
||||
// Nominal: 1kOhm, Beta: 3380, Step: 64
|
||||
const uint8_t ntc_step_size = 64;
|
||||
const int16_t ntc_lut[] = {
|
||||
1316, 197, 155, 133, 119, 108, 100, 93, 87, 82, 77, 73, 69, 66, 63, 60,
|
||||
57, 54, 52, 50, 47, 45, 43, 41, 39, 37, 35, 34, 32, 30, 28, 27,
|
||||
25, 23, 22, 20, 19, 17, 15, 14, 12, 11, 9, 7, 6, 4, 2, 0,
|
||||
-1, -3, -5, -7, -9, -11, -14, -16, -19, -22, -25, -28, -32, -38, -44, -55,
|
||||
-55 // extra value to not have an extra if statement
|
||||
};
|
||||
|
||||
|
||||
u8g2_t *u8g2;
|
||||
int16_t encoder = 0; // rotary encoder counter
|
||||
uint32_t last_interrupt = 0; // last time the encoder interrupt was triggered
|
||||
struct pd_profile_t pd_profile;
|
||||
static const int8_t x_off = 0;
|
||||
static const int8_t y_off = 8;
|
||||
|
||||
// Convert the raw adc reading to a temperature in celsius with the ntc lut,
|
||||
// linearly interpolating between positions
|
||||
static inline int16_t get_temp_c(uint16_t adc_reading)
|
||||
{
|
||||
if (adc_reading > 4095) return 0;
|
||||
uint8_t index = adc_reading / ntc_step_size;
|
||||
uint8_t remainder = adc_reading % ntc_step_size;
|
||||
int16_t temp_base = index < 64 ? ntc_lut[index] : 0;
|
||||
int16_t temp_next = ntc_lut[index + 1];
|
||||
return temp_base + ((temp_next - temp_base) * remainder)/ntc_step_size;
|
||||
}
|
||||
|
||||
|
||||
// convert the raw TPA191 adc reading to a current in milliamps
|
||||
static inline int16_t get_current_ma(uint16_t adc_reading)
|
||||
{
|
||||
// Rshunt = 4 milliOhm
|
||||
// Gain = 100
|
||||
u32 mv = ((u32)adc_reading * VCC_MV) / 4096;
|
||||
return (mv * 10) / 4;
|
||||
}
|
||||
|
||||
|
||||
void print_i2c_device(uint8_t addr)
|
||||
{
|
||||
printf("Device found at 0x%02X\n", addr);
|
||||
}
|
||||
|
||||
|
||||
// this callback is mandatory when FUNCONF_USE_USBPRINTF is defined,
|
||||
// can be empty though
|
||||
void handle_usbfs_input(int numbytes, uint8_t *data)
|
||||
{
|
||||
(void)numbytes;
|
||||
(void)data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* __ ____ ____
|
||||
* A: |____| |____| |____
|
||||
* ____ ____ __
|
||||
* B: ____| |____| |____|
|
||||
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||
* f r r f f r r f f r
|
||||
*/
|
||||
void update_encoder(void)
|
||||
{
|
||||
// 0 = 00, 1 = 01, 2 = 10, 3 = 11
|
||||
static uint8_t last_state = 0;
|
||||
// Lookup table: state_table[last_state][current_state]
|
||||
// 0 = invalid move or bounce (ignore)
|
||||
// 1 = valid forward step
|
||||
// -1 = valid backward step
|
||||
static const int8_t state_table[4][4] = {
|
||||
{ 0, 1, -1, 0}, // from 00
|
||||
{-1, 0, 0, 1}, // from 01
|
||||
{ 1, 0, 0, -1}, // from 10
|
||||
{ 0, -1, 1, 0} // from 11
|
||||
};
|
||||
|
||||
// FIXME: even with interrupts disabled and debounce, a single detent triggers
|
||||
// multiple interrupts, leading to multiple encoder updates in a short time.
|
||||
bool a = funDigitalRead(PIN_ENC_A);
|
||||
bool b = funDigitalRead(PIN_ENC_B);
|
||||
Delay_Us(100);
|
||||
if (a != funDigitalRead(PIN_ENC_A) || b != funDigitalRead(PIN_ENC_B))
|
||||
return; // debounce
|
||||
|
||||
uint8_t current_state = (a << 1) | b;
|
||||
|
||||
// Find the movement direction based on transition
|
||||
encoder += state_table[last_state][current_state];
|
||||
|
||||
// Save current state for the next interrupt
|
||||
last_state = current_state;
|
||||
}
|
||||
|
||||
// Attached to PIN_ENC_A rising and falling edges
|
||||
void EXTI7_0_IRQHandler(void) __attribute__((interrupt));
|
||||
void EXTI7_0_IRQHandler(void)
|
||||
{
|
||||
__disable_irq();
|
||||
update_encoder();
|
||||
EXTI->INTFR = EXTI_Line3;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
// Attached to PIN_ENC_B rising and falling edges
|
||||
void EXTI15_8_IRQHandler(void) __attribute__((interrupt));
|
||||
void EXTI15_8_IRQHandler(void)
|
||||
{
|
||||
__disable_irq();
|
||||
update_encoder();
|
||||
EXTI->INTFR = EXTI_Line11;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
|
||||
// Procedure to get hardware I2C working on the CH32X035F8U6
|
||||
static inline void setup_i2c(void)
|
||||
{
|
||||
// Order here matters, first initialize the AFIO and I2C subsystems then
|
||||
// change register values, do that the other way around and the configuration
|
||||
// wont take effect
|
||||
// Enable AFIO (Alternate Function IO)
|
||||
RCC->APB2PCENR |= RCC_AFIOEN;
|
||||
// Init I2C
|
||||
i2c_init(I2C_TARGET, FUNCONF_SYSTEM_CORE_CLOCK, 400000);
|
||||
|
||||
// To utilize the I2C bus we need to disable SWD first, since the pins overlap
|
||||
AFIO->PCFR1 &= ~(0b0111 << 24);
|
||||
AFIO->PCFR1 |= 0b0100 << 24;
|
||||
|
||||
// Map SCL to PC18 and SDA to PC19
|
||||
AFIO->PCFR1 |= 0b0101 << 2;
|
||||
// Manually set the I2C pins to Alternate Function IO, CNF=10b, MODE=10b
|
||||
GPIOC->CFGXR &= ~((0xF << 8) | (0xF << 12)); // first clear the bits
|
||||
// then set them
|
||||
GPIOC->CFGXR |= 0b1010 << 8; // PC18
|
||||
GPIOC->CFGXR |= 0b1010 << 12; // PC19
|
||||
}
|
||||
|
||||
|
||||
// FIXME: this holds the max number of ADC channels, ideally this would be lower
|
||||
volatile uint16_t adc_buffer[16];
|
||||
// Set-up the adc to perform continous conversion of enabled channels, enable
|
||||
// channel injection and setup DMA to automatically transfer conversion results
|
||||
// to a buffer
|
||||
static inline void setup_adc_and_dma(uint8_t *channels, uint8_t ch_size, uint8_t *injected, uint8_t in_size)
|
||||
{
|
||||
if (channels == NULL || ch_size == 0) return;
|
||||
// FIXME: for now only support a single configuration register, so at max 6 channels
|
||||
// I don't want to implement logic to switch registers right now
|
||||
// TODO: report an error
|
||||
if (ch_size > 6) return;
|
||||
|
||||
// General ADC initialization, I use this only for enabling clocks and such
|
||||
funAnalogInit(); // general initialization
|
||||
|
||||
// Set the SCAN and CONT bits to enter continous conversion mode
|
||||
// Do not set the IAUTO bit to ensure injected channels are converted only
|
||||
// when specified by software
|
||||
// Set the regular channel trigger mode to software (EXTSEL = 0b111) to ensure
|
||||
// conversion starts in sync with DMA (this should already be done by funAnalogInit())
|
||||
ADC1->CTLR1 |= ADC_SCAN;
|
||||
ADC1->CTLR2 |= ADC_CONT | ADC_EXTSEL;
|
||||
|
||||
// Setup regular channels (scanned continously)
|
||||
// TODO: setup sampling time
|
||||
for (uint8_t i = 0; i < ch_size; i++) {
|
||||
// Increase sampling time to have less cross talk between channels
|
||||
// 0b111 means 11 ADC clock cycles (max)
|
||||
if (channels[i] < 10) {
|
||||
ADC1->SAMPTR2 |= 0b111 << (channels[i]*3);
|
||||
} else {
|
||||
ADC1->SAMPTR1 |= 0b111 << ((channels[i]-10)*3);
|
||||
}
|
||||
ADC1->RSQR3 |= channels[i] << (i*5);
|
||||
}
|
||||
// Set the number of normal conversion channels
|
||||
ADC1->RSQR1 |= (ch_size-1) << 20;
|
||||
|
||||
// Set-up injection channels
|
||||
// The injection channel register allows for up to 4 channels, if the buffer is larger
|
||||
// skip this step
|
||||
// TODO: report an error
|
||||
if (injected != NULL && in_size != 0 && in_size <= 4) {
|
||||
// enable injection group
|
||||
// JEXTSEL = 0b111 (software trigger)
|
||||
ADC1->CTLR2 |= ADC_JEXTSEL;
|
||||
for (uint8_t i = 0; i < in_size; i++) {
|
||||
ADC1->ISQR |= injected[i] << ((4-in_size+i)*5);
|
||||
}
|
||||
// Set the number of injection channels
|
||||
ADC1->ISQR |= (in_size-1) << 20;
|
||||
}
|
||||
|
||||
// Set-up DMA, ADC is connected only to channel 1
|
||||
// Turn on DMA
|
||||
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
|
||||
// 1. Set the address of the source peripheral, in this case the output
|
||||
// register of the ADC
|
||||
DMA1_Channel1->PADDR = (uint32_t)&(ADC1->RDATAR);
|
||||
// 2. Set the destination (base) address of the data
|
||||
DMA1_Channel1->MADDR = (uint32_t)adc_buffer;
|
||||
// 3. Set the number of transfers to be done each cycle, in this case it's
|
||||
// the same as the number of regular conversion cycles
|
||||
DMA1_Channel1->CNTR = ch_size;
|
||||
// 4. Set mode: Peripheral to Memory, MEM2MEM=0 DIR=0
|
||||
// Circular mode CIRC=1, restart after CNTR transfers
|
||||
// Max priority to not lose conversions and offset values in the buffer
|
||||
DMA1_Channel1->CFGR =
|
||||
DMA_M2M_Disable |
|
||||
DMA_Priority_VeryHigh |
|
||||
DMA_MemoryDataSize_HalfWord |
|
||||
DMA_PeripheralDataSize_HalfWord |
|
||||
DMA_MemoryInc_Enable |
|
||||
DMA_Mode_Circular |
|
||||
DMA_DIR_PeripheralSRC;
|
||||
// Turn on DMA channel 1
|
||||
DMA1_Channel1->CFGR |= DMA_CFGR1_EN;
|
||||
|
||||
// Enable DMA requests from the ADC
|
||||
ADC1->CTLR2 |= ADC_DMA;
|
||||
// Power up ADC again
|
||||
ADC1->CTLR2 |= ADC_ADON;
|
||||
// start conversion
|
||||
ADC1->CTLR2 |= ADC_SWSTART;
|
||||
}
|
||||
|
||||
|
||||
// Perform a conversion on the injected ADC channels, this is synchronous and
|
||||
// halts conversion on the normal channels until it completes
|
||||
volatile uint16_t injection_results[4];
|
||||
static inline bool adc_injection_conversion() {
|
||||
// Clear any pending flags
|
||||
ADC1->STATR &= ~(ADC_JEOC);
|
||||
|
||||
// Start injection conversion using external trigger method
|
||||
ADC1->CTLR2 |= ADC_JSWSTART;
|
||||
|
||||
// Wait for all conversions to complete
|
||||
s32 timeout = 1000000;
|
||||
while(!(ADC1->STATR & ADC_JEOC) && timeout--) {}
|
||||
|
||||
if (timeout <= 0) return false;
|
||||
|
||||
// Read all results
|
||||
injection_results[0] = ADC1->IDATAR1 & 0x0FFF;
|
||||
injection_results[1] = ADC1->IDATAR2 & 0x0FFF;
|
||||
injection_results[2] = ADC1->IDATAR3 & 0x0FFF;
|
||||
injection_results[3] = ADC1->IDATAR4 & 0x0FFF;
|
||||
|
||||
// Clear JEOC flag
|
||||
ADC1->STATR &= ~ADC_JEOC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// mask for the CCxP bits
|
||||
// when set PWM outputs are held HIGH by default and pulled LOW
|
||||
// when zero PWM outputs are held LOW by default and pulled HIGH
|
||||
// #define TIM3_DEFAULT 0xff
|
||||
#define TIM3_DEFAULT 0x00
|
||||
static inline void setup_pwm(void)
|
||||
{
|
||||
// Enable TIM3 clock
|
||||
RCC->APB1PCENR |= RCC_APB1Periph_TIM3;
|
||||
|
||||
// Since TIM3 is enabled with TIM3->SMCFGR.SMS = 0b000 (default value) the
|
||||
// clock source is the internal clock
|
||||
// The internal clock goes through the HBB prescaler RCC->CFGR0.HPRE which
|
||||
// by default is disabled
|
||||
|
||||
// Reset TIM3 to init all regs
|
||||
RCC->APB1PRSTR |= RCC_APB1Periph_TIM3;
|
||||
RCC->APB1PRSTR &= ~RCC_APB1Periph_TIM3;
|
||||
|
||||
// set TIM3 clock prescaler divider
|
||||
TIM3->PSC = 0x0000; // no prescaler
|
||||
// set PWM total cycle width
|
||||
static_assert((FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1) < 0xffff, "PWM_FREQ_HZ too low for TIM3");
|
||||
TIM3->ATRLR = FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1;
|
||||
|
||||
// for channel 1 let CCxS stay 00 (output), set OC1M to 110 (PWM 1)
|
||||
// enabling preload (OC1PE) causes the new pulse width in compare capture
|
||||
// register only to come into effect when UG bit in SWEVGR is set
|
||||
// (= initiate update) (auto-clears)
|
||||
TIM3->CHCTLR1 |= TIM_OC1M_2 | TIM_OC1M_1 | TIM_OC1PE;
|
||||
|
||||
// Enable channel 1 output (PA6)
|
||||
TIM3->CCER |= TIM_CC1E | ( TIM_CC1P & TIM3_DEFAULT );
|
||||
|
||||
// CTLR1: default is up, events generated, edge align
|
||||
// enable auto-reload of preload
|
||||
TIM3->CTLR1 |= TIM_ARPE;
|
||||
}
|
||||
|
||||
|
||||
static inline void pwm_on(void)
|
||||
{
|
||||
// initialize counter
|
||||
TIM3->SWEVGR |= TIM_UG;
|
||||
// Enable TIM3
|
||||
TIM3->CTLR1 |= TIM_CEN;
|
||||
}
|
||||
|
||||
|
||||
static inline void pwm_off(void)
|
||||
{
|
||||
// Disable TIM3
|
||||
TIM3->CTLR1 &= ~TIM_CEN;
|
||||
TIM3->CH1CVR = 0;
|
||||
}
|
||||
|
||||
|
||||
static inline void pwm_set(uint16_t pulse_width)
|
||||
{
|
||||
TIM3->CH1CVR = pulse_width;
|
||||
}
|
||||
|
||||
|
||||
// Integer square root (binary search)
|
||||
// https://en.wikipedia.org/wiki/Integer_square_root
|
||||
static inline uint16_t isqrt(uint32_t x)
|
||||
{
|
||||
uint16_t l = 0; // lower bound of the square root
|
||||
uint16_t r = x + 1; // upper bound of the square root
|
||||
|
||||
while (l != r - 1) {
|
||||
uint32_t m = (l + r) / 2; // midpoint to test
|
||||
if (m * m <= x) {
|
||||
l = m;
|
||||
} else {
|
||||
r = m;
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
__attribute__((noreturn)) int main(void)
|
||||
{
|
||||
SystemInit();
|
||||
funGpioInitAll();
|
||||
USBFSSetup();
|
||||
|
||||
funPinMode(PIN_VBUS, GPIO_CFGLR_IN_ANALOG);
|
||||
funPinMode(PIN_CURRENT, GPIO_CFGLR_IN_ANALOG);
|
||||
funPinMode(PIN_NTC, GPIO_CFGLR_IN_ANALOG);
|
||||
funPinMode(PIN_TEMP, GPIO_CFGLR_IN_ANALOG);
|
||||
|
||||
uint8_t adc_channels[3] = {
|
||||
VBUS_ADC_CHANNEL,
|
||||
CURRENT_ADC_CHANNEL,
|
||||
NTC_ADC_CHANNEL
|
||||
};
|
||||
uint8_t adc_injected[1] = {
|
||||
TEMP_ADC_CHANNEL
|
||||
};
|
||||
setup_adc_and_dma(adc_channels, 3, adc_injected, 1);
|
||||
|
||||
funPinMode(PIN_12V, GPIO_CFGLR_OUT_10Mhz_PP);
|
||||
funDigitalWrite(PIN_12V, 0);
|
||||
funPinMode(PIN_HEATER, GPIO_CFGLR_OUT_10Mhz_AF_PP);
|
||||
funDigitalWrite(PIN_HEATER, 0);
|
||||
funPinMode(PIN_DISP_RST, GPIO_CFGLR_OUT_10Mhz_PP);
|
||||
funDigitalWrite(PIN_DISP_RST, 1); // start with display disabled
|
||||
|
||||
funPinMode(PIN_ENC_A, GPIO_CFGLR_IN_PUPD); // enable pull-up/down
|
||||
funDigitalWrite(PIN_ENC_A, 1); // specify pull-up
|
||||
funPinMode(PIN_ENC_B, GPIO_CFGLR_IN_PUPD); // enable pull-up/down
|
||||
funDigitalWrite(PIN_ENC_B, 1); // specify pull-up
|
||||
funPinMode(PIN_BTN, GPIO_CFGLR_IN_FLOAT);
|
||||
|
||||
setup_pwm();
|
||||
pwm_off();
|
||||
|
||||
setup_i2c();
|
||||
|
||||
// Configure the IO as an interrupt.
|
||||
// PIN_ENC_B is on port B, channel 11
|
||||
AFIO->EXTICR1 |= AFIO_EXTICR1_EXTI11_PB; // Port B channel (pin) 11
|
||||
EXTI->INTENR |= EXTI_INTENR_MR11; // Enable EXT11
|
||||
EXTI->FTENR |= EXTI_FTENR_TR11; // Falling edge trigger
|
||||
EXTI->RTENR |= EXTI_RTENR_TR11; // Rising edge trigger
|
||||
// enable interrupt
|
||||
NVIC_EnableIRQ(EXTI15_8_IRQn);
|
||||
|
||||
// PIN_ENC_A is on port B, channel 3
|
||||
AFIO->EXTICR1 |= AFIO_EXTICR1_EXTI3_PB; // Port B channel (pin) 3
|
||||
EXTI->INTENR |= EXTI_INTENR_MR3; // Enable EXT3
|
||||
EXTI->FTENR |= EXTI_FTENR_TR3; // Falling edge trigger
|
||||
EXTI->RTENR |= EXTI_RTENR_TR3; // Rising edge trigger
|
||||
// enable interrupt
|
||||
NVIC_EnableIRQ(EXTI7_0_IRQn);
|
||||
|
||||
Delay_Ms(500);
|
||||
|
||||
u8g2 = display_init();
|
||||
sc7a20_init();
|
||||
|
||||
u8g2_ClearBuffer(u8g2);
|
||||
u8g2_SetBitmapMode(u8g2, 1);
|
||||
u8g2_SetFontMode(u8g2, 1);
|
||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "Negotiating...");
|
||||
u8g2_SendBuffer(u8g2);
|
||||
|
||||
// Init USBPD
|
||||
bool has_pd = pd_negotiate(eUSBPD_VCC_3V3);
|
||||
if (has_pd == false) {
|
||||
u8g2_ClearBuffer(u8g2);
|
||||
u8g2_SetBitmapMode(u8g2, 1);
|
||||
u8g2_SetFontMode(u8g2, 1);
|
||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "Negotiation FAILED");
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+14, USBPD_ResultToStr(pd_get_result()));
|
||||
u8g2_SendBuffer(u8g2);
|
||||
Delay_Ms(5000);
|
||||
} else {
|
||||
pd_get_profile(&pd_profile, 60);
|
||||
|
||||
// TODO: let the user decide the power profile
|
||||
pd_profile.set_temp = 200;
|
||||
pd_profile.set_power = 60; // Slightly below max power to avoid overloading
|
||||
pd_profile.tip_r = 2500; // TODO: tip check and resistance calculator
|
||||
pd_profile.max_duty = MIN(
|
||||
(100*(u32)isqrt((
|
||||
MIN(pd_profile.set_power, pd_profile.power_avail)*pd_profile.tip_r)/1000) * 1000) / pd_profile.voltage
|
||||
, 100);
|
||||
|
||||
u8g2_ClearBuffer(u8g2);
|
||||
u8g2_SetBitmapMode(u8g2, 1);
|
||||
u8g2_SetFontMode(u8g2, 1);
|
||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||
// Display tip temperature
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "A:");
|
||||
u8g2_DrawStr(u8g2, x_off+10, y_off+7, u8g2_u16toa(pd_profile.max_current, 4));
|
||||
// Display bus voltage
|
||||
u8g2_DrawStr(u8g2, x_off+45, y_off+7, "V:");
|
||||
u8g2_DrawStr(u8g2, x_off+55, y_off+7, u8g2_u16toa(pd_profile.voltage, 5));
|
||||
// Display power
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+15, "W:");
|
||||
u8g2_DrawStr(u8g2, x_off+10, y_off+15, u8g2_u16toa(pd_profile.power_avail, 3));
|
||||
// Display current
|
||||
u8g2_DrawStr(u8g2, x_off+45, y_off+15, "D:");
|
||||
u8g2_DrawStr(u8g2, x_off+55, y_off+15, u8g2_u16toa(pd_profile.max_duty, 3));
|
||||
u8g2_SendBuffer(u8g2);
|
||||
Delay_Ms(5000);
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
STATE_MENU,
|
||||
STATE_HEATING,
|
||||
} state = STATE_MENU;
|
||||
for (;;) {
|
||||
u32 start = funSysTick32();
|
||||
poll_input(); // usb
|
||||
|
||||
u8g2_ClearBuffer(u8g2);
|
||||
u8g2_SetBitmapMode(u8g2, 1);
|
||||
u8g2_SetFontMode(u8g2, 1);
|
||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||
|
||||
static bool pwm = false; // PWM status
|
||||
static bool enabled = false; // Power electronics enabled
|
||||
static uint8_t count = 0; // Loop cycles with PWM on
|
||||
static s32 elapsed = 0;
|
||||
static bool prev_btn = true;
|
||||
bool btn = funDigitalRead(PIN_BTN);
|
||||
|
||||
if (has_pd) {
|
||||
static uint16_t vbus_mv, current_ma;
|
||||
static int16_t temp_c, tip_temp_c;
|
||||
static uint16_t power;
|
||||
vbus_mv = U16_FP_EMA_K4(vbus_mv, ((u32)adc_buffer[0]*VCC_MV*11)/4096);
|
||||
current_ma = U16_FP_EMA_K4(current_ma, get_current_ma(adc_buffer[1]));
|
||||
temp_c = I16_FP_EMA_K4(temp_c, get_temp_c(adc_buffer[2]));
|
||||
power = ((u32)vbus_mv*current_ma)/1000000;
|
||||
|
||||
// Update the tip temperature only when the PWM is not running
|
||||
if (!pwm || !enabled) {
|
||||
Delay_Ms(TURN_OFF_DELAY);
|
||||
adc_injection_conversion();
|
||||
u32 tip_mv = ((u32)injection_results[0]*VCC_MV)/4096;
|
||||
tip_temp_c = I16_FP_EMA_K2(tip_temp_c, (tip_mv*TC_CONV_NOM)/TC_CONV_DEN) + temp_c;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case STATE_MENU:
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TEMP:");
|
||||
u8g2_DrawStr(u8g2, x_off+25, y_off+7, u8g2_u16toa(pd_profile.set_temp, 4));
|
||||
|
||||
if (encoder != 0) {
|
||||
pd_profile.set_temp += encoder;
|
||||
encoder = 0;
|
||||
#define MIN_TEMP 100
|
||||
#define MAX_TEMP 360
|
||||
if (pd_profile.set_temp < MIN_TEMP) pd_profile.set_temp = MIN_TEMP;
|
||||
if (pd_profile.set_temp > MAX_TEMP) pd_profile.set_temp = MAX_TEMP;
|
||||
}
|
||||
|
||||
if (btn == 0 && prev_btn == 1) {
|
||||
state = STATE_HEATING;
|
||||
enabled = false;
|
||||
}
|
||||
break;
|
||||
case STATE_HEATING:
|
||||
// Display tip temperature
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TIP:");
|
||||
u8g2_DrawStr(u8g2, x_off+20, y_off+7, u8g2_u16toa(tip_temp_c, 4));
|
||||
// Display bus voltage
|
||||
u8g2_DrawStr(u8g2, x_off+45, y_off+7, "V:");
|
||||
u8g2_DrawStr(u8g2, x_off+55, y_off+7, u8g2_u16toa(vbus_mv/1000, 2));
|
||||
// Display power
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+15, "W:");
|
||||
u8g2_DrawStr(u8g2, x_off+10, y_off+15, u8g2_u16toa(power, 3));
|
||||
// Display current
|
||||
u8g2_DrawStr(u8g2, x_off+45, y_off+15, "A:");
|
||||
u8g2_DrawStr(u8g2, x_off+55, y_off+15, u8g2_u16toa(current_ma, 5));
|
||||
|
||||
|
||||
if (enabled) {
|
||||
funDigitalWrite(PIN_12V, 1);
|
||||
|
||||
if (count > CYCLES_PER_MEASURE) {
|
||||
pwm = false;
|
||||
count = 0;
|
||||
} else {
|
||||
pwm = true;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Safety logic
|
||||
if (current_ma > pd_profile.max_current + pd_profile.max_current/10) {
|
||||
pwm = false;
|
||||
}
|
||||
if (temp_c > MAX_BOARD_TEMP) {
|
||||
enabled = false;
|
||||
pwm = false;
|
||||
}
|
||||
if (tip_temp_c > MAX_TIP_TEMP) {
|
||||
enabled = false;
|
||||
pwm = false;
|
||||
}
|
||||
|
||||
if (pwm) {
|
||||
const uint16_t tim_max = FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1;
|
||||
int16_t delta = pd_profile.set_temp - tip_temp_c;
|
||||
uint16_t duty = MIN((25*pd_profile.max_duty*delta)/(pd_profile.set_temp*10), pd_profile.max_duty);
|
||||
pwm_set(((u32)duty*tim_max)/100);
|
||||
u8g2_DrawBox(u8g2, x_off+92, y_off+12, 4, 4);
|
||||
} else {
|
||||
pwm_set(0);
|
||||
}
|
||||
} else {
|
||||
funDigitalWrite(PIN_12V, 0);
|
||||
}
|
||||
|
||||
// move to menu mode when encoder is turned
|
||||
if (encoder != 0) {
|
||||
state = STATE_MENU;
|
||||
funDigitalWrite(PIN_12V, 0);
|
||||
pwm_set(0);
|
||||
}
|
||||
|
||||
// Check button to toggle enable
|
||||
if (btn == 0 && prev_btn == 1) {
|
||||
enabled = !enabled;
|
||||
if (enabled) {
|
||||
pwm_on();
|
||||
} else {
|
||||
pwm_off();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// No PD capability, just display a message
|
||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "NO PD");
|
||||
}
|
||||
|
||||
u8g2_SendBuffer(u8g2);
|
||||
|
||||
prev_btn = btn;
|
||||
|
||||
elapsed = funSysTick32() - start;
|
||||
if (elapsed > 0 && elapsed < Ticks_from_Ms(FRAME_TIME_MS)) {
|
||||
DelaySysTick(Ticks_from_Ms(FRAME_TIME_MS) - elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
127
fw/pd.c
Normal file
127
fw/pd.c
Normal file
@ -0,0 +1,127 @@
|
||||
#include <ch32fun.h>
|
||||
|
||||
#define USBPD_IMPLEMENTATION
|
||||
#include "usbpd.h"
|
||||
|
||||
#include "funconfig.h"
|
||||
#include "display.h"
|
||||
|
||||
#include "pd.h"
|
||||
|
||||
|
||||
extern u8g2_t *u8g2;
|
||||
|
||||
static size_t cap_count = 0;
|
||||
static USBPD_SPR_CapabilitiesMessage_t *capabilities = NULL;
|
||||
static USBPD_Result_e result;
|
||||
|
||||
|
||||
USBPD_Result_e pd_get_result()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Initializes the Power Delivery peripheral and starts the Power Delivery
|
||||
// negotiation, returns true if successful, indicating the board is connected to
|
||||
// a Power Delivery source.
|
||||
// As a side effect, fills the capabilities buffer with the source's capabilities.
|
||||
bool pd_negotiate(USBPD_VCC_e vcc)
|
||||
{
|
||||
result = USBPD_Init(vcc);
|
||||
if (result != eUSBPD_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Delay_Ms(100);
|
||||
|
||||
u32 start = funSysTick32();
|
||||
while (eUSBPD_BUSY == (result = USBPD_SinkNegotiate())) {
|
||||
u32 now = funSysTick32();
|
||||
if (now - start > Ticks_from_Ms(5000)) {
|
||||
break;
|
||||
}
|
||||
|
||||
u8g2_ClearBuffer(u8g2);
|
||||
u8g2_SetBitmapMode(u8g2, 1);
|
||||
u8g2_SetFontMode(u8g2, 1);
|
||||
u8g2_SetFont(u8g2, u8g2_font_5x8_tr);
|
||||
u8g2_DrawStr(u8g2, 0, 8+7, USBPD_StateToStr(USBPD_GetState()));
|
||||
u8g2_SendBuffer(u8g2);
|
||||
|
||||
Delay_Ms(1);
|
||||
}
|
||||
if (result != eUSBPD_OK) {
|
||||
return false;
|
||||
}
|
||||
cap_count = USBPD_GetCapabilities(&capabilities);
|
||||
if (capabilities == NULL || cap_count == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool pd_get_profile(struct pd_profile_t *profile, uint16_t min_power)
|
||||
{
|
||||
if (profile == NULL || min_power == 0 || min_power > 140) {
|
||||
return false;
|
||||
}
|
||||
if (capabilities == NULL || cap_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u16 voltage = 0, current = 0, power = 0;
|
||||
for (u32 i = 0; i < cap_count; i++) {
|
||||
USBPD_SinkPDO_t *pdo = &capabilities->Sink[i];
|
||||
switch (pdo->Header.PDOType) {
|
||||
case eUSBPD_PDO_FIXED:
|
||||
voltage = pdo->FixedSupply.VoltageIn50mV * 50;
|
||||
current = pdo->FixedSupply.CurrentIn10mA * 10;
|
||||
power = ((u32)voltage * current) / (u32)1000000;
|
||||
break;
|
||||
case eUSBPD_PDO_BATTERY:
|
||||
voltage = pdo->BatterySupply.MaxVoltageIn50mV * 50;
|
||||
power = pdo->BatterySupply.MaxPowerIn250mW / 4;
|
||||
current = ((u32)power * 1000) / voltage;
|
||||
break;
|
||||
case eUSBPD_PDO_VARIABLE:
|
||||
// TODO: PPS
|
||||
// if (pdo->VariableSupply.MaxVoltageIn50mV/20 > max_v) {
|
||||
// max_v = pdo->VariableSupply.MaxVoltageIn50mV/20;
|
||||
// }
|
||||
break;
|
||||
case eUSBPD_PDO_AUGMENTED:
|
||||
switch (pdo->Header.AugmentedType) {
|
||||
case eUSBPD_APDO_SPR_PPS:
|
||||
// TODO: SPR_PPS
|
||||
break;
|
||||
case eUSBPD_APDO_SPR_AVS:
|
||||
// TODO: SPR AVS
|
||||
break;
|
||||
case eUSBPD_APDO_EPR_AVS:
|
||||
/* TODO: EPR AVS
|
||||
voltage = pdo->EPR_AVS.MaxVoltageIn100mV * 100;
|
||||
current = pdo->EPR_AVS.PeakCurrent * 1000;
|
||||
power = pdo->EPR_AVS.PDPIn1W;
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Selects the first PDO that meets the minimum power requirement
|
||||
if (power >= min_power && voltage <= BOARD_MAX_VOLTAGE) {
|
||||
if (USBPD_SelectPDO(i, 0) != eUSBPD_OK) {
|
||||
return false;
|
||||
}
|
||||
profile->voltage = voltage;
|
||||
profile->max_current = current;
|
||||
profile->power_avail = power;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
25
fw/pd.h
Normal file
25
fw/pd.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef _PD_H
|
||||
#define _PD_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "usbpd.h"
|
||||
|
||||
|
||||
struct pd_profile_t {
|
||||
uint16_t voltage; // Vbus Voltage in millivolts
|
||||
uint16_t max_current; // Maximum current in milliamps
|
||||
uint16_t power_avail; // Available power (from supply) in watts
|
||||
uint16_t set_power; // Maximum power in watts, set by the user
|
||||
uint16_t set_temp; // Set temperature in celsius, set by the user
|
||||
uint16_t tip_r; // Tip resistance in milliOhms
|
||||
uint8_t max_duty; // Maximum duty cycle (0-100) to stay within the power limit
|
||||
};
|
||||
|
||||
|
||||
USBPD_Result_e pd_get_result();
|
||||
bool pd_negotiate(USBPD_VCC_e vcc);
|
||||
bool pd_get_profile(struct pd_profile_t *profile, uint16_t min_power);
|
||||
|
||||
#endif // _PD_H
|
||||
5
fw/programmer/.gitignore
vendored
Normal file
5
fw/programmer/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.zed
|
||||
.vscode
|
||||
.cache
|
||||
compile_commands.json
|
||||
14
fw/programmer/platformio.ini
Normal file
14
fw/programmer/platformio.ini
Normal file
@ -0,0 +1,14 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:default]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi
|
||||
framework = arduino
|
||||
board = rpipico
|
||||
1096
fw/programmer/src/bitbang_rvswdio.h
Normal file
1096
fw/programmer/src/bitbang_rvswdio.h
Normal file
File diff suppressed because it is too large
Load Diff
197
fw/programmer/src/bitbang_rvswdio_pico.h
Normal file
197
fw/programmer/src/bitbang_rvswdio_pico.h
Normal file
@ -0,0 +1,197 @@
|
||||
#include <hardware/gpio.h>
|
||||
#include <pico/time.h>
|
||||
|
||||
#include "bitbang_rvswdio.h"
|
||||
#include "hardware/timer.h"
|
||||
#include "lwipopts.h"
|
||||
#include "pico.h"
|
||||
|
||||
|
||||
#define PIN_SWDIO 10
|
||||
#define PIN_SWCLK 11
|
||||
|
||||
|
||||
// wait time between line transitions
|
||||
#define SWD_DELAY() busy_wait_us(2);
|
||||
|
||||
// microseconds between each register read/write
|
||||
#define STOP_WAIT 8
|
||||
|
||||
// Single wire debug (SWDIO and SWCLK)
|
||||
static inline void ConfigureIOForRVSWD(void)
|
||||
{
|
||||
// SWCLK forced, starts at 1
|
||||
gpio_init(PIN_SWCLK);
|
||||
gpio_set_pulls(PIN_SWCLK, false, false);
|
||||
gpio_put(PIN_SWCLK, 1);
|
||||
gpio_set_dir(PIN_SWCLK, GPIO_OUT);
|
||||
|
||||
// SWDIO, open drain (emulated) with pull-up
|
||||
gpio_init(PIN_SWDIO);
|
||||
gpio_set_pulls(PIN_SWDIO, true, false);
|
||||
gpio_put(PIN_SWDIO, 1);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_IN);
|
||||
}
|
||||
|
||||
|
||||
// Single wire input-output SDI (just SWDIO)
|
||||
static inline void ConfigureIOForRVSWIO(void)
|
||||
{
|
||||
//BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" );
|
||||
}
|
||||
|
||||
|
||||
void rvswd_write_bit(bool value)
|
||||
{
|
||||
gpio_put(PIN_SWCLK, 0);
|
||||
gpio_put(PIN_SWDIO, value);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_OUT);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_IN);
|
||||
SWD_DELAY();
|
||||
gpio_put(PIN_SWCLK, 1); // Data is sampled on rising edge of clock
|
||||
SWD_DELAY();
|
||||
}
|
||||
|
||||
|
||||
bool rvswd_read_bit(void)
|
||||
{
|
||||
gpio_put(PIN_SWDIO, 1);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_IN);
|
||||
gpio_put(PIN_SWCLK, 0);
|
||||
SWD_DELAY();
|
||||
bool bit = gpio_get(PIN_SWDIO);
|
||||
gpio_put(PIN_SWCLK, 1); // Data is output on rising edge of clock
|
||||
SWD_DELAY();
|
||||
return bit;
|
||||
}
|
||||
|
||||
|
||||
static inline void rvswd_stop(void)
|
||||
{
|
||||
gpio_put(PIN_SWCLK, 0);
|
||||
SWD_DELAY();
|
||||
gpio_put(PIN_SWDIO, 0);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_OUT);
|
||||
SWD_DELAY();
|
||||
gpio_put(PIN_SWCLK, 1);
|
||||
SWD_DELAY();
|
||||
gpio_put(PIN_SWDIO, 1);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_IN);
|
||||
}
|
||||
|
||||
|
||||
static void MCFWriteReg32( struct SWIOState * state, uint8_t command, uint32_t value )
|
||||
{
|
||||
// only supported mode is SWD
|
||||
if (state->opmode != 2) {
|
||||
//BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
noInterrupts();
|
||||
|
||||
// start transaction
|
||||
gpio_put(PIN_SWDIO, 0);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_OUT);
|
||||
SWD_DELAY();
|
||||
|
||||
// ADDR HOST
|
||||
bool parity = true;
|
||||
for (uint32_t mask = 1<<6; mask; mask >>= 1) {
|
||||
bool bit = !!(command & mask);
|
||||
parity ^= bit;
|
||||
rvswd_write_bit(bit);
|
||||
}
|
||||
|
||||
rvswd_write_bit(1); // Operation: write
|
||||
rvswd_write_bit(parity);
|
||||
rvswd_read_bit(); // ???
|
||||
rvswd_read_bit(); // Seems only need to be set for first transaction (We are ignoring that though)
|
||||
rvswd_read_bit(); // ???
|
||||
rvswd_write_bit(0); // 0 for register, 1 for value.
|
||||
rvswd_write_bit(0); // ??? Seems to have something to do with halting.
|
||||
|
||||
// DATA
|
||||
parity = false; // This time it's even parity?
|
||||
for (uint32_t mask = 1<<31; mask; mask >>= 1) {
|
||||
bool bit = !!(value & mask);
|
||||
parity ^= bit;
|
||||
rvswd_write_bit(bit);
|
||||
}
|
||||
|
||||
// Parity bit
|
||||
rvswd_write_bit(parity);
|
||||
|
||||
rvswd_read_bit(); // ???
|
||||
rvswd_read_bit(); // ???
|
||||
rvswd_read_bit(); // ???
|
||||
rvswd_write_bit(1); // 0 for register, 1 for value
|
||||
rvswd_write_bit(0); // ??? Seems to have something to do with halting?
|
||||
|
||||
rvswd_stop();
|
||||
interrupts();
|
||||
sleep_us(STOP_WAIT);
|
||||
}
|
||||
|
||||
|
||||
static int MCFReadReg32( struct SWIOState * state, uint8_t command, uint32_t * value )
|
||||
{
|
||||
// only supported mode is SWD
|
||||
if (state->opmode != 2) {
|
||||
//BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
noInterrupts();
|
||||
|
||||
// start transaction
|
||||
gpio_put(PIN_SWDIO, 0);
|
||||
gpio_set_dir(PIN_SWDIO, GPIO_OUT);
|
||||
SWD_DELAY();
|
||||
|
||||
// ADDR HOST
|
||||
bool parity = false;
|
||||
for (uint8_t mask = 1<<6; mask; mask >>= 1) {
|
||||
bool bit = !!(command & mask);
|
||||
parity ^= bit;
|
||||
rvswd_write_bit(bit);
|
||||
}
|
||||
|
||||
rvswd_write_bit(0); // Operation: read
|
||||
rvswd_write_bit(parity);
|
||||
rvswd_read_bit(); // ??
|
||||
rvswd_read_bit(); // ??
|
||||
rvswd_read_bit(); // ??
|
||||
rvswd_write_bit(0); // 0 for register, 1 for value
|
||||
rvswd_write_bit(0); // ??? Seems to have something to do with halting?
|
||||
|
||||
// DATA
|
||||
*value = 0;
|
||||
parity = false;
|
||||
uint32_t rval = 0;
|
||||
for (uint8_t position = 0; position < 32; position++) {
|
||||
bool bit = rvswd_read_bit();
|
||||
rval <<= 1;
|
||||
rval |= bit;
|
||||
parity ^= bit;
|
||||
}
|
||||
*value = rval;
|
||||
|
||||
// Parity bit
|
||||
bool parity_read = rvswd_read_bit();
|
||||
if (parity_read != parity) goto read_end;
|
||||
|
||||
rvswd_read_bit(); // ??
|
||||
rvswd_read_bit(); // ??
|
||||
rvswd_read_bit(); // ??
|
||||
rvswd_write_bit(1); // 0 for register, 1 for value
|
||||
rvswd_write_bit(0); // ??? Seems to have something to do with halting?
|
||||
|
||||
rvswd_stop();
|
||||
|
||||
read_end:
|
||||
interrupts();
|
||||
sleep_us(STOP_WAIT);
|
||||
BB_PRINTF_DEBUG("wrong parity: %d\n", parity_read);
|
||||
return (parity == parity_read) ? 0 : -1;
|
||||
}
|
||||
59
fw/programmer/src/main.cpp
Normal file
59
fw/programmer/src/main.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "pico/time.h"
|
||||
#include <Arduino.h>
|
||||
#include <SerialUSB.h>
|
||||
|
||||
#define BB_PRINTF_DEBUG(...) Serial.printf(__VA_ARGS__)
|
||||
//#define BB_PRINTF_DEBUG(...)
|
||||
#include "bitbang_rvswdio.h"
|
||||
#include "bitbang_rvswdio_pico.h"
|
||||
|
||||
SWIOState state = {.opmode = 2};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(100);
|
||||
}
|
||||
|
||||
|
||||
void setup1()
|
||||
{
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
if (Serial.available() > 0) {
|
||||
char cmd = Serial.read();
|
||||
int ret = 0;
|
||||
uint8_t reg;
|
||||
|
||||
switch (cmd) {
|
||||
case '!':
|
||||
state = {};
|
||||
ret = InitializeSWDSWIO(&state);
|
||||
if (ret != 0) {
|
||||
Serial.printf("error initializing SWD: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
ret = DetermineChipTypeAndSectorInfo(&state, NULL);
|
||||
if (ret != 0) {
|
||||
Serial.printf("failed to determine chip type: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
Serial.printf("chip type is %x\n", state.target_chip_type);
|
||||
break;
|
||||
default:
|
||||
Serial.printf("unknown command '%c'\n", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop1()
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, 1);
|
||||
delay(200);
|
||||
digitalWrite(LED_BUILTIN, 0);
|
||||
delay(200);
|
||||
}
|
||||
199
fw/programmer/test/rvswd.c
Normal file
199
fw/programmer/test/rvswd.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include "rvswd.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <pico/time.h>
|
||||
|
||||
|
||||
// adapted from https://github.com/Nicolai-Electronics/esp32-component-rvswd
|
||||
|
||||
rvswd_result_t rvswd_init(rvswd_handle_t* handle) {
|
||||
//gpio_config_t swio_cfg = {
|
||||
// .pin_bit_mask = BIT64(handle->swdio),
|
||||
// .mode = GPIO_MODE_INPUT_OUTPUT_OD,
|
||||
// .pull_up_en = true,
|
||||
// .pull_down_en = false,
|
||||
// .intr_type = GPIO_INTR_DISABLE,
|
||||
//};
|
||||
gpio_init(handle->swdio);
|
||||
gpio_set_pulls(handle->swdio, true, false);
|
||||
gpio_put(handle->swdio, 0);
|
||||
gpio_set_dir(handle->swdio, GPIO_IN);
|
||||
|
||||
//gpio_config_t swck_cfg = {
|
||||
// .pin_bit_mask = BIT64(handle->swclk),
|
||||
// .mode = GPIO_MODE_OUTPUT,
|
||||
// .pull_up_en = false,
|
||||
// .pull_down_en = false,
|
||||
// .intr_type = GPIO_INTR_DISABLE,
|
||||
//};
|
||||
gpio_init(handle->swclk);
|
||||
gpio_set_pulls(handle->swclk, false, false);
|
||||
gpio_put(handle->swclk, 0);
|
||||
gpio_set_dir(handle->swclk, GPIO_OUT);
|
||||
|
||||
return RVSWD_OK;
|
||||
}
|
||||
|
||||
rvswd_result_t rvswd_start(rvswd_handle_t* handle) {
|
||||
// Start with both lines high
|
||||
// open drain emulation, input for high (pulled up) and out for low (forced)
|
||||
gpio_set_dir(handle->swdio, GPIO_IN); // high
|
||||
gpio_put(handle->swclk, 1);
|
||||
sleep_us(2);
|
||||
|
||||
// Pull data low
|
||||
gpio_set_dir(handle->swdio, GPIO_OUT); // low
|
||||
gpio_put(handle->swclk, 1);
|
||||
sleep_us(1);
|
||||
|
||||
// Pull clock low
|
||||
gpio_set_dir(handle->swdio, GPIO_OUT); // low
|
||||
gpio_put(handle->swclk, 0);
|
||||
sleep_us(1);
|
||||
|
||||
return RVSWD_OK;
|
||||
}
|
||||
|
||||
rvswd_result_t rvswd_stop(rvswd_handle_t* handle) {
|
||||
// Pull data low
|
||||
gpio_set_dir(handle->swdio, GPIO_OUT);
|
||||
sleep_us(1);
|
||||
gpio_put(handle->swclk, 1);
|
||||
sleep_us(2);
|
||||
|
||||
// Let data float high
|
||||
gpio_set_dir(handle->swdio, GPIO_IN);
|
||||
sleep_us(1);
|
||||
return RVSWD_OK;
|
||||
}
|
||||
|
||||
rvswd_result_t rvswd_reset(rvswd_handle_t* handle) {
|
||||
// set data floating high
|
||||
gpio_set_dir(handle->swdio, GPIO_IN);
|
||||
sleep_us(1);
|
||||
// let clock go brrr
|
||||
for (uint8_t i = 0; i < 100; i++) {
|
||||
gpio_put(handle->swclk, 0);
|
||||
sleep_us(1);
|
||||
gpio_put(handle->swclk, 1);
|
||||
sleep_us(1);
|
||||
}
|
||||
return rvswd_stop(handle);
|
||||
}
|
||||
|
||||
#define OD_PULL(pin, value) gpio_set_dir((pin), (value) ? GPIO_IN : GPIO_OUT)
|
||||
|
||||
void rvswd_write_bit(rvswd_handle_t* handle, bool value) {
|
||||
OD_PULL(handle->swdio, value);
|
||||
gpio_put(handle->swclk, 0);
|
||||
// FIXME: does this need a delay?
|
||||
gpio_put(handle->swclk, 1); // Data is sampled on rising edge of clock
|
||||
}
|
||||
|
||||
bool rvswd_read_bit(rvswd_handle_t* handle) {
|
||||
// let data float high
|
||||
gpio_set_dir(handle->swdio, GPIO_IN);
|
||||
// pulse clock
|
||||
gpio_put(handle->swclk, 0);
|
||||
gpio_put(handle->swclk, 1); // Data is output on rising edge of clock
|
||||
// FIXME: does this need a delay?
|
||||
return gpio_get(handle->swdio);
|
||||
}
|
||||
|
||||
rvswd_result_t rvswd_write(rvswd_handle_t* handle, uint8_t reg, uint32_t value) {
|
||||
rvswd_start(handle);
|
||||
|
||||
// ADDR HOST
|
||||
bool parity = false; // This time it's odd parity?
|
||||
for (uint8_t position = 0; position < 7; position++) {
|
||||
bool bit = (reg >> (6 - position)) & 1;
|
||||
rvswd_write_bit(handle, bit);
|
||||
if (bit) parity = !parity;
|
||||
}
|
||||
|
||||
// Operation: write
|
||||
rvswd_write_bit(handle, true);
|
||||
parity = !parity;
|
||||
|
||||
// Parity bit (even)
|
||||
rvswd_write_bit(handle, parity);
|
||||
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 0);
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 0);
|
||||
rvswd_write_bit(handle, 1);
|
||||
|
||||
// Data
|
||||
parity = false; // This time it's even parity?
|
||||
for (uint8_t position = 0; position < 32; position++) {
|
||||
bool bit = (value >> (31 - position)) & 1;
|
||||
rvswd_write_bit(handle, bit);
|
||||
if (bit) parity = !parity;
|
||||
}
|
||||
|
||||
// Parity bit
|
||||
rvswd_write_bit(handle, parity);
|
||||
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 0);
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 1);
|
||||
|
||||
rvswd_stop(handle);
|
||||
|
||||
return RVSWD_OK;
|
||||
}
|
||||
|
||||
rvswd_result_t rvswd_read(rvswd_handle_t* handle, uint8_t reg, uint32_t* value) {
|
||||
bool parity;
|
||||
|
||||
rvswd_start(handle);
|
||||
|
||||
// ADDR HOST
|
||||
parity = false;
|
||||
for (uint8_t position = 0; position < 7; position++) {
|
||||
bool bit = (reg >> (6 - position)) & 1;
|
||||
rvswd_write_bit(handle, bit);
|
||||
if (bit) parity = !parity;
|
||||
}
|
||||
|
||||
// Operation: read
|
||||
rvswd_write_bit(handle, false);
|
||||
|
||||
// Parity bit (even)
|
||||
rvswd_write_bit(handle, parity);
|
||||
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 0);
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 0);
|
||||
rvswd_write_bit(handle, 1);
|
||||
|
||||
*value = 0;
|
||||
|
||||
// Data
|
||||
parity = false;
|
||||
for (uint8_t position = 0; position < 32; position++) {
|
||||
bool bit = rvswd_read_bit(handle);
|
||||
if (bit) {
|
||||
*value |= 1 << (31 - position);
|
||||
}
|
||||
if (bit) parity = !parity;
|
||||
}
|
||||
|
||||
// Parity bit
|
||||
bool parity_read = rvswd_read_bit(handle);
|
||||
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 0);
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 1);
|
||||
rvswd_write_bit(handle, 1);
|
||||
|
||||
rvswd_stop(handle);
|
||||
|
||||
return (parity == parity_read) ? RVSWD_OK : RVSWD_FAIL;
|
||||
}
|
||||
20
fw/programmer/test/rvswd.h
Normal file
20
fw/programmer/test/rvswd.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct rvswd_handle {
|
||||
int swdio;
|
||||
int swclk;
|
||||
} rvswd_handle_t;
|
||||
|
||||
typedef enum rvswd_result {
|
||||
RVSWD_OK = 0,
|
||||
RVSWD_FAIL = 1,
|
||||
RVSWD_INVALID_ARGS = 2,
|
||||
RVSWD_PARITY_ERROR = 3,
|
||||
} rvswd_result_t;
|
||||
|
||||
rvswd_result_t rvswd_init(rvswd_handle_t* handle);
|
||||
rvswd_result_t rvswd_reset(rvswd_handle_t* handle);
|
||||
rvswd_result_t rvswd_write(rvswd_handle_t* handle, uint8_t reg, uint32_t value);
|
||||
rvswd_result_t rvswd_read(rvswd_handle_t* handle, uint8_t reg, uint32_t* value);
|
||||
54
fw/sc7a20.c
Normal file
54
fw/sc7a20.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include <ch32fun.h>
|
||||
#include "lib_i2c.h"
|
||||
|
||||
#include "sc7a20.h"
|
||||
|
||||
|
||||
// Initialization values for control registers, in reg-value pairs
|
||||
// Basically setup the unit to run, and enable 4D orientation detection
|
||||
// TODO: Make better comments and define values
|
||||
static const uint8_t i2c_registers[][2] = {
|
||||
{ SC7A20_CTRL_REG1, 0b01100111}, // 200Hz, XYZ enabled
|
||||
{ SC7A20_CTRL_REG2, 0b00000000}, // Setup filter to 0x00 ??
|
||||
{ SC7A20_CTRL_REG3, 0b00000000}, // INT1 off
|
||||
{ SC7A20_CTRL_REG4, 0b00001000}, // Block mode off,little-endian,2G,High-pres,self test off
|
||||
{ SC7A20_CTRL_REG5, 0b00000100}, // fifo off, D4D on INT1
|
||||
{ SC7A20_CTRL_REG6, 0x00}, // INT2 off
|
||||
{ SC7A20_INT2_CFG, 0b01111110}, // setup for movement detection
|
||||
{ SC7A20_INT2_THS, 0x28}, //
|
||||
{SC7A20_INT2_DURATION, 64}, //
|
||||
{ SC7A20_INT1_CFG, 0b01111110}, //
|
||||
{ SC7A20_INT1_THS, 0x28}, //
|
||||
{SC7A20_INT1_DURATION, 64}
|
||||
};
|
||||
|
||||
|
||||
void sc7a20_init()
|
||||
{
|
||||
// Setup acceleration readings
|
||||
// 2G range
|
||||
// bandwidth = 250Hz
|
||||
// High pass filter on (Slow compensation)
|
||||
// Turn off IRQ output pins
|
||||
// Orientation recognition in symmetrical mode
|
||||
// Hysteresis is set to ~ 16 counts
|
||||
// Theta blocking is set to 0b10
|
||||
for (uint8_t i = 0; i < sizeof(i2c_registers) / sizeof(i2c_registers[0]); i++) {
|
||||
uint8_t bytes[2] = {i2c_registers[i][0], i2c_registers[i][1]};
|
||||
i2c_sendBytes(I2C_TARGET, SC7A20_ADDRESS, bytes, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void sc7a20_get_readings(int16_t *x, int16_t *y, int16_t *z)
|
||||
{
|
||||
// We can tell the accelerometer to output in LE mode which makes this simple
|
||||
int16_t sensorData[3] = {0};
|
||||
|
||||
i2c_sendByte(I2C_TARGET, SC7A20_ADDRESS, SC7A20_OUT_X_L | 0x80);
|
||||
i2c_readBytes(I2C_TARGET, SC7A20_ADDRESS, (u8*)sensorData, 6);
|
||||
|
||||
// Lower byte is sent first
|
||||
*x = (int16_t)sensorData[0];
|
||||
*y = (int16_t)sensorData[1];
|
||||
*z = (int16_t)sensorData[2];
|
||||
}
|
||||
56
fw/sc7a20.h
Normal file
56
fw/sc7a20.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SC7A20_defines.h
|
||||
*
|
||||
* Created on: 18 Sep. 2020
|
||||
* Author: Ralim
|
||||
*/
|
||||
|
||||
#ifndef _SC7A20_H_
|
||||
#define _SC7A20_H_
|
||||
|
||||
#include <ch32fun.h>
|
||||
|
||||
#define SC7A20_ADDRESS 0x18
|
||||
|
||||
#define SC7A20_WHO_AM_I_VALUE (0b00010001)
|
||||
#define SC7A20_WHO_AMI_I 0x0F
|
||||
#define SC7A20_CTRL_REG1 0x20
|
||||
#define SC7A20_CTRL_REG2 0x21
|
||||
#define SC7A20_CTRL_REG3 0x22
|
||||
#define SC7A20_CTRL_REG4 0x23
|
||||
#define SC7A20_CTRL_REG5 0x24
|
||||
#define SC7A20_CTRL_REG6 0x25
|
||||
#define SC7A20_REFERENCE 0x26
|
||||
#define SC7A20_STATUS_REG 0x27
|
||||
#define SC7A20_OUT_X_L 0x28
|
||||
#define SC7A20_OUT_X_L_ALT 0xA8
|
||||
#define SC7A20_OUT_X_H 0x29
|
||||
#define SC7A20_OUT_Y_L 0x2A
|
||||
#define SC7A20_OUT_Y_H 0x2B
|
||||
#define SC7A20_OUT_Z_L 0x2C
|
||||
#define SC7A20_OUT_Z_H 0x2D
|
||||
#define SC7A20_FIFO_CTRL 0x2E
|
||||
#define SC7A20_FIFO_SRC 0x2F
|
||||
#define SC7A20_INT1_CFG 0x30
|
||||
#define SC7A20_INT1_SOURCE 0x31
|
||||
#define SC7A20_INT1_THS 0x32
|
||||
#define SC7A20_INT1_DURATION 0x33
|
||||
#define SC7A20_INT2_CFG 0x34
|
||||
#define SC7A20_INT2_SOURCE 0x35
|
||||
#define SC7A20_INT2_THS 0x36
|
||||
#define SC7A20_INT2_DURATION 0x37
|
||||
#define SC7A20_CLICK_CFG 0x38
|
||||
#define SC7A20_CLICK_SRC 0x39
|
||||
#define SC7A20_CLICK_THS 0x3A
|
||||
#define SC7A20_TIME_LIMIT 0x3B
|
||||
#define SC7A20_TIME_LATENCY 0x3C
|
||||
#define SC7A20_TIME_WINDOW 0x3D
|
||||
#define SC7A20_ACT_THS 0x3E
|
||||
#define SC7A20_ACT_DURATION 0x3F
|
||||
|
||||
|
||||
void sc7a20_init(void);
|
||||
void sc7a20_get_readings(int16_t *x, int16_t *y, int16_t *z);
|
||||
|
||||
|
||||
#endif /* CORE_DRIVERS_BMA223_DEFINES_H_ */
|
||||
59
fw/script/ntc_lut.py
Executable file
59
fw/script/ntc_lut.py
Executable file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
|
||||
# Script to generate NTC lookup table
|
||||
# ^ Vcc
|
||||
# |
|
||||
# [RES]
|
||||
# |
|
||||
# +-- Vadc
|
||||
# |
|
||||
# [NTC]
|
||||
# |
|
||||
# _|_ GND
|
||||
# ///
|
||||
|
||||
adc_res = 12
|
||||
ntc_value = 10_000 # at 25°C
|
||||
resistor_value = 10_000
|
||||
ntc_beta = 3380 # at 25°C
|
||||
steps = 64
|
||||
|
||||
# NTC resistance to temperature (°C) conversion
|
||||
def resistance_to_t(ntc_r):
|
||||
# Standard B-parameter equation
|
||||
# T = 1 / (1/T0 + 1/B * ln(R/R0))
|
||||
inv_t = 1/(25 + 273.15) + math.log(ntc_r/ntc_value)/ntc_beta
|
||||
return 1/inv_t - 273.15
|
||||
|
||||
# Resistor divider percentage to NTC resistance conversion
|
||||
# x = NTC / (NTC + RES) => NTC = RES * x / (1 - x)
|
||||
def x_to_r(x):
|
||||
x = max(0.0001, min(0.9999, x))
|
||||
return resistor_value * x / (1 - x)
|
||||
|
||||
# Use 4096 for cleaner divisions
|
||||
adc_max = 2**adc_res
|
||||
step_size = adc_max // steps
|
||||
|
||||
values = []
|
||||
for i in range(steps):
|
||||
adc_val = i * step_size
|
||||
x = adc_val / adc_max
|
||||
r = x_to_r(adc_val / adc_max)
|
||||
t = resistance_to_t(r)
|
||||
values.append(int(round(t)))
|
||||
|
||||
def to_c_array(values, ctype="float", name="table", formatter=str, colcount=8):
|
||||
# apply formatting to each element
|
||||
values = [formatter(v) for v in values]
|
||||
# split into rows with up to `colcount` elements per row
|
||||
rows = [values[i:i+colcount] for i in range(0, len(values), colcount)]
|
||||
# separate elements with commas, separate rows with newlines
|
||||
body = ',\n '.join([', '.join(r) for r in rows])
|
||||
# assemble components into the complete string
|
||||
return '{} {}[] = {{\n {}}};'.format(ctype, name, body)
|
||||
|
||||
print("uint8_t ntc_step_size = {};".format(int(step_size)))
|
||||
print(to_c_array(values, ctype="int16_t", name="ntc_lut", formatter=str, colcount=16))
|
||||
1
fw/u8g2
Submodule
1
fw/u8g2
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 3b8939cd015d6aca6a19f761df84859916f1f7d9
|
||||
182
fw/usb_config.h
Normal file
182
fw/usb_config.h
Normal file
@ -0,0 +1,182 @@
|
||||
#ifndef _USB_CONFIG_H
|
||||
#define _USB_CONFIG_H
|
||||
|
||||
#include "funconfig.h"
|
||||
#include "ch32fun.h"
|
||||
|
||||
// Endpoint numbers, at least one (EP0)
|
||||
#define FUSB_CONFIG_EPS 4
|
||||
// Endpoint configuration for CDC TTY
|
||||
#define FUSB_EP1_MODE 1 // TX (IN), CDC Interrupt Endpoint
|
||||
#define FUSB_EP2_MODE -1 // RX (OUT), CDC Data OUT
|
||||
#define FUSB_EP3_MODE 1 // TX (IN), CDC Data IN
|
||||
// Other hardware configuration
|
||||
#define FUSB_SUPPORTS_SLEEP 0
|
||||
#define FUSB_HID_INTERFACES 0
|
||||
#define FUSB_CURSED_TURBO_DMA 0 // Hacky, but seems fine, shaves 2.5us off filling 64-byte buffers.
|
||||
#define FUSB_HID_USER_REPORTS 0
|
||||
#define FUSB_IO_PROFILE 0
|
||||
#define FUSB_USE_HPE FUNCONF_ENABLE_HPE
|
||||
#define FUSB_USER_HANDLERS 1
|
||||
#define FUSB_USE_DMA7_COPY 0
|
||||
#define FUSB_VDD_5V 0 // 3.3V
|
||||
|
||||
#include "usb_defines.h"
|
||||
|
||||
#define FUSB_USB_VID 0x1209
|
||||
#define FUSB_USB_PID 0xd035
|
||||
#define FUSB_USB_REV 0x0007
|
||||
#define FUSB_STR_MANUFACTURER u"ch32fun"
|
||||
#define FUSB_STR_PRODUCT u"USB TTY"
|
||||
#define FUSB_STR_SERIAL u"007"
|
||||
|
||||
//Taken from http://www.usbmadesimple.co.uk/ums_ms_desc_dev.htm
|
||||
static const uint8_t device_descriptor[] = {
|
||||
18, //bLength - Length of this descriptor
|
||||
1, //bDescriptorType - Type (Device)
|
||||
0x10, 0x01, //bcdUSB - The highest USB spec version this device supports (USB1.1)
|
||||
0x02, //bDeviceClass - Device Class
|
||||
0x0, //bDeviceSubClass - Device Subclass
|
||||
0x0, //bDeviceProtocol - Device Protocol (000 = use config descriptor)
|
||||
64, //bMaxPacketSize - Max packet size for EP0
|
||||
(uint8_t)(FUSB_USB_VID), (uint8_t)(FUSB_USB_VID >> 8), //idVendor - ID Vendor
|
||||
(uint8_t)(FUSB_USB_PID), (uint8_t)(FUSB_USB_PID >> 8), //idProduct - ID Product
|
||||
(uint8_t)(FUSB_USB_REV), (uint8_t)(FUSB_USB_REV >> 8), //bcdDevice - Device Release Number
|
||||
1, //iManufacturer - Index of Manufacturer string
|
||||
2, //iProduct - Index of Product string
|
||||
3, //iSerialNumber - Index of Serial string
|
||||
1, //bNumConfigurations - Max number of configurations (if more then 1, you can switch between them)
|
||||
};
|
||||
|
||||
/* Configuration Descriptor Set */
|
||||
static const uint8_t config_descriptor[ ] =
|
||||
{
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x43, 0x00, // wTotalLength 67
|
||||
0x02, // bNumInterfaces 2
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x32, // bMaxPower 100mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType - Interface
|
||||
0x00, // bInterfaceNumber - 0
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints - 1
|
||||
0x02, // bInterfaceClass - CDC
|
||||
0x02, // bInterfaceSubClass - Abstract Control Model (Table 4 in CDC120.pdf)
|
||||
0x01, // bInterfaceProtocol - AT Commands: V.250 etc (Table 5)
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
// Setting up CDC interface (Table 18)
|
||||
0x05, // bLength
|
||||
0x24, // bDescriptorType - CS_INTERFACE (Table 12)
|
||||
0x00, // bDescriptorSubType - Header Functional Descriptor (Table 13)
|
||||
0x10, 0x01, // bcdCDC - USB version - USB1.1
|
||||
// Call Management Functional Descriptor
|
||||
0x05, // bLength
|
||||
0x24, // bDescriptorType - CS_INTERFACE
|
||||
0x01, // bDescriptorSubType - Call Management Functional Descriptor (Table 13)
|
||||
0x00, // bmCapabilities: (Table 3 in PSTN120.pdf)
|
||||
// Bit 0 — Device handles call management itself:
|
||||
// 1 = device handles call management (e.g. call setup, termination, etc.)
|
||||
// 0 = host handles it
|
||||
// Bit 1 — Device can send/receive call management information over a Data Class interface:
|
||||
// 1 = can use the Data Class interface for call management
|
||||
// 0 = must use the Communication Class interface
|
||||
0x01, // bDataInterface - Indicates that multiplexed commands are handled via data interface 01h (same value as used in the UNION Functional Descriptor)
|
||||
// Abstract Control Management Functional Descriptor
|
||||
0x04, // bLength
|
||||
0x24, // bDescriptorType - CS_INTERFACE
|
||||
0x02, // bDescriptorSubType - Abstract Control Management Functional Descriptor (Table 13)
|
||||
0x02, // bmCapabilities - Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State (Table 4 in PSTN120.pdf)
|
||||
// Union Descriptor Functional Descriptor
|
||||
0x05, // bLength
|
||||
0x24, // bDescriptorType - CS_INTERFACE
|
||||
0x06, // bDescriptorSubType - Union Descriptor Functional Descriptor (Table 13)
|
||||
0x00, // bControlInterface (Interface number of the control (Communications Class) interface)
|
||||
0x01, // bSubordinateInterface0 (Interface number of the subordinate (Data Class) interface)
|
||||
// Setting up EP1 for CDC config interface
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x01, // bInterval 1 (unit depends on device speed)
|
||||
|
||||
// Transmission interface with two bulk endpoints
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x01, // bInterfaceNumber 1
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints 2
|
||||
0x0A, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol - Transparent
|
||||
0x00, // iInterface (String Index)
|
||||
// EP2 - device to host
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x02, // bEndpointAddress (OUT/H2D)
|
||||
0x02, // bmAttributes (Bulk)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x00, // bInterval 0 (unit depends on device speed)
|
||||
// EP3 - host to device
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x83, // bEndpointAddress (IN/D2H)
|
||||
0x02, // bmAttributes (Bulk)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x00, // bInterval 0 (unit depends on device speed)
|
||||
|
||||
// 67 bytes
|
||||
};
|
||||
|
||||
struct usb_string_descriptor_struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wString[];
|
||||
};
|
||||
const static struct usb_string_descriptor_struct language __attribute__((section(".rodata"))) = {
|
||||
4,
|
||||
3,
|
||||
{0x0409} // Language ID - English US (look in USB_LANGIDs)
|
||||
};
|
||||
const static struct usb_string_descriptor_struct string1 __attribute__((section(".rodata"))) = {
|
||||
sizeof(FUSB_STR_MANUFACTURER),
|
||||
3, // bDescriptorType - String Descriptor (0x03)
|
||||
FUSB_STR_MANUFACTURER
|
||||
};
|
||||
const static struct usb_string_descriptor_struct string2 __attribute__((section(".rodata"))) = {
|
||||
sizeof(FUSB_STR_PRODUCT),
|
||||
3,
|
||||
FUSB_STR_PRODUCT
|
||||
};
|
||||
const static struct usb_string_descriptor_struct string3 __attribute__((section(".rodata"))) = {
|
||||
sizeof(FUSB_STR_SERIAL),
|
||||
3,
|
||||
FUSB_STR_SERIAL
|
||||
};
|
||||
|
||||
// This table defines which descriptor data is sent for each specific
|
||||
// request from the host (in wValue and wIndex).
|
||||
const static struct descriptor_list_struct {
|
||||
uint32_t lIndexValue; // (uint16_t)Index of a descriptor in config or Language ID for string descriptors | (uint8_t)Descriptor type | (uint8_t)Type of string descriptor
|
||||
const uint8_t *addr;
|
||||
uint8_t length;
|
||||
} descriptor_list[] = {
|
||||
{0x00000100, device_descriptor, sizeof(device_descriptor)},
|
||||
{0x00000200, config_descriptor, sizeof(config_descriptor)},
|
||||
// {0x00002100, config_descriptor + 18, 9 }, // Not sure why, this seems to be useful for Windows + Android.
|
||||
|
||||
{0x00000300, (const uint8_t *)&language, 4},
|
||||
{0x04090301, (const uint8_t *)&string1, string1.bLength},
|
||||
{0x04090302, (const uint8_t *)&string2, string2.bLength},
|
||||
{0x04090303, (const uint8_t *)&string3, string3.bLength}
|
||||
};
|
||||
#define DESCRIPTOR_LIST_ENTRIES ((sizeof(descriptor_list))/(sizeof(struct descriptor_list_struct)) )
|
||||
|
||||
|
||||
#endif
|
||||
937
fw/usbpd.h
Normal file
937
fw/usbpd.h
Normal file
@ -0,0 +1,937 @@
|
||||
/* USB PD Library
|
||||
* 2025-06-21 Bogdan Ionescu
|
||||
* Configuration:
|
||||
* - USBPD_IMPLEMENTATION: Enable USB PD implementation
|
||||
* - FUNCONF_USBPD_NO_STR: Disable string conversion functions
|
||||
* Notes:
|
||||
* - This library is based on the USB Power Delivery Specification.
|
||||
* https://www.usb.org/document-library/usb-power-delivery
|
||||
* - Packed bitfield structs are used for de/serialization of USB PD messages and
|
||||
* are taken directly from the spec above.
|
||||
* - Not all messages are implemented.
|
||||
* - Formatting macros are provided next to the struct deffinitions.
|
||||
* Basic usage:
|
||||
* USBPD_VCC_e vcc = eUSBPD_VCC_5V0; // set the VCC voltage
|
||||
* USBPD_Result_e result = USBPD_Init( vcc ); // initialize the peripheral
|
||||
*
|
||||
* // wait for negotiation to complete.
|
||||
* while ( eUSBPD_BUSY == ( result = USBPD_SinkNegotiate() ) );
|
||||
*
|
||||
* USBPD_SPR_CapabilitiesMessage_t *capabilities;
|
||||
* const size_t count = USBPD_GetCapabilities( &capabilities );
|
||||
* USBPD_SelectPDO( count - 1, voltage ); // select the last supply (voltage is only used for PPS)
|
||||
*
|
||||
* The above is not a complete example, check the funtion declarations below for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ch32fun.h"
|
||||
#include "funconfig.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef PACKED
|
||||
#define PACKED __attribute__( ( packed ) )
|
||||
#endif
|
||||
|
||||
// USB PD spec type definitions
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_PORTDATAROLE_DFP = 0, // Downstream Facing Port
|
||||
eUSBPD_PORTDATAROLE_UFP = 1, // Upstream Facing Port
|
||||
} USBPD_PortDataRole_e;
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_PORTPOWEROLE_SINK = 0, // Sink Power Role
|
||||
eUSBPD_PORTPOWEROLE_SOURCE = 1, // Source Power Role
|
||||
} USBPD_PortPowerRole_e;
|
||||
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_REV_10 = 0x00u, // Revision 1.0
|
||||
eUSBPD_REV_20 = 0x01u, // Revision 2.0
|
||||
eUSBPD_REV_30 = 0x02u, // Revision 3.0
|
||||
} USBPD_SpecificationRevision_e;
|
||||
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_CTRL_MSG_GOODCRC = 0x01u,
|
||||
eUSBPD_CTRL_MSG_GOTOMIN = 0x02u, // Depracated
|
||||
eUSBPD_CTRL_MSG_ACCEPT = 0x03u,
|
||||
eUSBPD_CTRL_MSG_REJECT = 0x04u,
|
||||
eUSBPD_CTRL_MSG_PING = 0x05u, // Deprecated
|
||||
eUSBPD_CTRL_MSG_PS_RDY = 0x06u,
|
||||
eUSBPD_CTRL_MSG_GET_SOURCE_CAP = 0x07u,
|
||||
eUSBPD_CTRL_MSG_GET_SINK_CAP = 0x08u,
|
||||
eUSBPD_CTRL_MSG_DR_SWAP = 0x09u,
|
||||
eUSBPD_CTRL_MSG_PR_SWAP = 0x0Au,
|
||||
eUSBPD_CTRL_MSG_VCONN_SWAP = 0x0Bu,
|
||||
eUSBPD_CTRL_MSG_WAIT = 0x0Cu,
|
||||
eUSBPD_CTRL_MSG_SOFT_RESET = 0x0Du,
|
||||
eUSBPD_CTRL_MSG_DATA_RESET = 0x0Eu,
|
||||
eUSBPD_CTRL_MSG_DATA_RESET_COMPLETE = 0x0Fu,
|
||||
eUSBPD_CTRL_MSG_NOT_SUPPORTED = 0x10u,
|
||||
eUSBPD_CTRL_MSG_GET_SOURCE_CAPEXT = 0x11u,
|
||||
eUSBPD_CTRL_MSG_GET_STATUS = 0x12u,
|
||||
eUSBPD_CTRL_MSG_FR_SWAP = 0x13u,
|
||||
eUSBPD_CTRL_MSG_GET_PPS_STATUS = 0x14u,
|
||||
eUSBPD_CTRL_MSG_GET_COUNTRY_CODES = 0x15u,
|
||||
eUSBPD_CTRL_MSG_GET_SINK_CAPEXT = 0x16u,
|
||||
eUSBPD_CTRL_MSG_GET_SOURCE_INFO = 0x17u,
|
||||
eUSBPD_CTRL_MSG_GET_REVISION = 0x18u,
|
||||
} USBPD_ControlMessage_e;
|
||||
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_DATA_MSG_SOURCE_CAP = 0x01u,
|
||||
eUSBPD_DATA_MSG_REQUEST = 0x02u,
|
||||
eUSBPD_DATA_MSG_BIST = 0x03u,
|
||||
eUSBPD_DATA_MSG_SINK_CAP = 0x04u,
|
||||
eUSBPD_DATA_MSG_BATTERY_STATUS = 0x05u,
|
||||
eUSBPD_DATA_MSG_ALERT = 0x06u,
|
||||
eUSBPD_DATA_MSG_GET_COUNTRY_INFO = 0x07u,
|
||||
eUSBPD_DATA_MSG_ENTER_USB = 0x08u,
|
||||
eUSBPD_DATA_MSG_EPR_REUEST = 0x09u,
|
||||
eUSBPD_DATA_MSG_EPR_MODE = 0x0Au,
|
||||
eUSBPD_DATA_MSG_SOURCE_INFO = 0x0Bu,
|
||||
eUSBPD_DATA_MSG_REVISION = 0x0Cu,
|
||||
eUSBPD_DATA_MSG_VENDOR_DEFINED = 0x0Fu
|
||||
} USBPD_DataMessage_e;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint16_t data;
|
||||
struct
|
||||
{
|
||||
uint16_t MessageType : 5u; // USBPD_ControlMessage_t | USBPD_DataMessage_t
|
||||
USBPD_PortDataRole_e PortDataRole : 1u;
|
||||
USBPD_SpecificationRevision_e SpecificationRevision : 2u;
|
||||
USBPD_PortPowerRole_e PortPowerRole : 1u;
|
||||
uint16_t MessageID : 3u;
|
||||
uint16_t NumberOfDataObjects : 3u; // 0: Control Message, >0: Data Message
|
||||
uint16_t Extended : 1u;
|
||||
};
|
||||
} USBPD_MessageHeader_t;
|
||||
|
||||
typedef USBPD_MessageHeader_t USBPD_ControlMessage_t;
|
||||
static_assert( sizeof( USBPD_MessageHeader_t ) == sizeof( uint16_t ), "USBPD_MessageHeader_t size mismatch" );
|
||||
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_PDO_FIXED = 0,
|
||||
eUSBPD_PDO_BATTERY = 1,
|
||||
eUSBPD_PDO_VARIABLE = 2,
|
||||
eUSBPD_PDO_AUGMENTED = 3,
|
||||
} USBPD_PowerDataObject_e;
|
||||
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_APDO_SPR_PPS = 0, // Standard Power Range Programmable Power Supply
|
||||
eUSBPD_APDO_EPR_AVS = 1, // Extended Power Range Adjustable Voltage Supply
|
||||
eUSBPD_APDO_SPR_AVS = 2, // Standard Power Range Adjustable Voltage Supply
|
||||
eUSBPD_APDO_RESERVED = 3,
|
||||
} USBPD_AugmentedPDO_e;
|
||||
|
||||
typedef enum PACKED
|
||||
{
|
||||
eUSBPD_PEAK_CURRENT_0 = 0, /* Peak Current equals IoC */
|
||||
|
||||
eUSBPD_PEAK_CURRENT_1 = 1, /* 150% IoC for 1ms @ 5% duty cycle
|
||||
125% IoC for 2ms @ 10% duty cycle
|
||||
110% IoC for 10ms @ 50% duty cycle */
|
||||
|
||||
eUSBPD_PEAK_CURRENT_2 = 2, /* 200% IoC for 1ms @ 5% duty cycle
|
||||
150% IoC for 2ms @ 10% duty cycle
|
||||
125% IoC for 10ms @ 50% duty cycle */
|
||||
|
||||
eUSBPD_PEAK_CURRENT_3 = 3, /* 200% IoC for 1ms @ 5% duty cycle
|
||||
175% IoC for 2ms @ 10% duty cycle
|
||||
150% IoC for 10ms @ 50% duty cycle */
|
||||
} USBPD_PeakCurrent_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t data : 28u; // PDO specific data based on PDO type
|
||||
USBPD_AugmentedPDO_e AugmentedType : 2u; // shall be eUSBPD_APDO_SPR_PPS
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_AUGMENTED
|
||||
} USBPD_PDOHeader_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxCurrentIn10mA : 10u;
|
||||
uint32_t VoltageIn50mV : 10u;
|
||||
USBPD_PeakCurrent_e PeakCurrent : 2u;
|
||||
uint32_t Reserved_22bit : 1u;
|
||||
uint32_t EPRModeCapable : 1u;
|
||||
uint32_t UnchunkedExtendedMessage : 1u;
|
||||
uint32_t DualRoleData : 1u;
|
||||
uint32_t USBCommunicationsCapable : 1u;
|
||||
uint32_t UnconstrainedPower : 1u;
|
||||
uint32_t USBSuspendSupported : 1u;
|
||||
uint32_t DualRolePower : 1u;
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_FIXED
|
||||
} USBPD_SourceFixedSupplyPDO_t;
|
||||
|
||||
#define FIXED_SUPPLY_FMT \
|
||||
"\nFixed Supply:\n" \
|
||||
"\tMax Current: %d mA\n" \
|
||||
"\tVoltage: %d mV\n" \
|
||||
"\tPeak Current: %d\n" \
|
||||
"\tEPR Mode Capable: %s\n" \
|
||||
"\tUnchunked Extended Message: %s\n" \
|
||||
"\tDual Role Data: %s\n" \
|
||||
"\tUSB Communications Capable: %s\n" \
|
||||
"\tUnconstrained Power: %s\n" \
|
||||
"\tUSB Suspend Supported: %s\n" \
|
||||
"\tDual Role Power: %s\n"
|
||||
|
||||
#define FIXED_SUPPLY_FMT_ARGS( pdo ) \
|
||||
( ( pdo )->FixedSupply.MaxCurrentIn10mA * 10 ), ( ( pdo )->FixedSupply.VoltageIn50mV * 50 ), \
|
||||
( ( pdo )->FixedSupply.PeakCurrent ), ( ( pdo )->FixedSupply.EPRModeCapable ? "Yes" : "No" ), \
|
||||
( ( pdo )->FixedSupply.UnchunkedExtendedMessage ? "Yes" : "No" ), \
|
||||
( ( pdo )->FixedSupply.DualRoleData ? "Yes" : "No" ), \
|
||||
( ( pdo )->FixedSupply.USBCommunicationsCapable ? "Yes" : "No" ), \
|
||||
( ( pdo )->FixedSupply.UnconstrainedPower ? "Yes" : "No" ), \
|
||||
( ( pdo )->FixedSupply.USBSuspendSupported ? "Yes" : "No" ), \
|
||||
( ( pdo )->FixedSupply.DualRolePower ? "Yes" : "No" )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxCurrentIn10mA : 10u;
|
||||
uint32_t MinVoltageIn50mV : 10u;
|
||||
uint32_t MaxVoltageIn50mV : 10u;
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_VARIABLE
|
||||
} USBPD_VariablePDO_t;
|
||||
|
||||
#define VARIABLE_SUPPLY_FMT \
|
||||
"\nVariable Supply:\n" \
|
||||
"\tMax Current: %d mA\n" \
|
||||
"\tMin Voltage: %d mV\n" \
|
||||
"\tMax Voltage: %d mV\n"
|
||||
|
||||
#define VARIABLE_SUPPLY_FMT_ARGS( pdo ) \
|
||||
( ( pdo )->VariableSupply.MaxCurrentIn10mA * 10 ), ( ( pdo )->VariableSupply.MinVoltageIn50mV * 50 ), \
|
||||
( ( pdo )->VariableSupply.MaxVoltageIn50mV * 50 )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxPowerIn250mW : 10u;
|
||||
uint32_t MinVoltageIn50mV : 10u;
|
||||
uint32_t MaxVoltageIn50mV : 10u;
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_BATTERY
|
||||
} USBPD_BatteryPDO_t;
|
||||
|
||||
#define BATTERY_SUPPLY_FMT \
|
||||
"\nBattery Supply:\n" \
|
||||
"\tMax Power: %d mW\n" \
|
||||
"\tMin Voltage: %d mV\n" \
|
||||
"\tMax Voltage: %d mV\n"
|
||||
|
||||
#define BATTERY_SUPPLY_FMT_ARGS( pdo ) \
|
||||
( ( pdo )->BatterySupply.MaxPowerIn250mW * 250 ), ( ( pdo )->BatterySupply.MinVoltageIn50mV * 50 ), \
|
||||
( ( pdo )->BatterySupply.MaxVoltageIn50mV * 50 )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxCurrentIn50mA : 7u;
|
||||
uint32_t Reserved_7bit : 1u; // shall be set to zero
|
||||
uint32_t MinVoltageIn100mV : 8u;
|
||||
uint32_t Reserved_16bit : 1u; // shall be set to zero
|
||||
uint32_t MaxVoltageIn100mV : 8u;
|
||||
uint32_t Reserved_25_26bit : 2u; // shall be set to zero
|
||||
uint32_t PPSpowerLimited : 1u;
|
||||
USBPD_AugmentedPDO_e AugmentedType : 2u; // shall be eUSBPD_APDO_SPR_PPS
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_AUGMENTED
|
||||
} USBPD_SPR_PPS_APDO_t;
|
||||
|
||||
#define SPR_PPS_FMT \
|
||||
"\nPPS Supply:\n" \
|
||||
"\tMax Current: %d mA\n" \
|
||||
"\tMin Voltage: %d mV\n" \
|
||||
"\tMax Voltage: %d mV\n" \
|
||||
"\tPPS Power Limited: %s\n"
|
||||
|
||||
#define SPR_PPS_FMT_ARGS( pdo ) \
|
||||
( ( pdo )->SPR_PPS.MaxCurrentIn50mA * 50 ), ( ( pdo )->SPR_PPS.MinVoltageIn100mV * 100 ), \
|
||||
( ( pdo )->SPR_PPS.MaxVoltageIn100mV * 100 ), ( ( pdo )->SPR_PPS.PPSpowerLimited ? "Yes" : "No" )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t PDPIn1W : 8u;
|
||||
uint32_t MinVoltageIn100mV : 8u;
|
||||
uint32_t Reserved_16bit : 1u; // shall be set to zero
|
||||
uint32_t MaxVoltageIn100mV : 9u;
|
||||
USBPD_PeakCurrent_e PeakCurrent : 2u;
|
||||
|
||||
USBPD_AugmentedPDO_e AugmentedType : 2u; // shall be eUSBPD_APDO_EPR_AVS
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_AUGMENTED
|
||||
} USBPD_EPR_AVS_APDO_t;
|
||||
|
||||
#define EPR_AVS_FMT \
|
||||
"\nEPR AVS Supply:\n" \
|
||||
"\tPDP: %d W\n" \
|
||||
"\tMin Voltage: %d mV\n" \
|
||||
"\tMax Voltage: %d mV\n" \
|
||||
"\tPeak Current: %d\n"
|
||||
|
||||
#define EPR_AVS_FMT_ARGS( pdo ) \
|
||||
( ( pdo )->EPR_AVS.PDPIn1W ), ( ( pdo )->EPR_AVS.MinVoltageIn100mV * 100 ), \
|
||||
( ( pdo )->EPR_AVS.MaxVoltageIn100mV * 100 ), ( ( pdo )->EPR_AVS.PeakCurrent )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxCurrent15To20VIn10mA : 10u;
|
||||
uint32_t MaxCurrent9to15VIn10mA : 10u;
|
||||
uint32_t Reserved_20_25bit : 6u; // shall be set to zero
|
||||
USBPD_PeakCurrent_e PeakCurrent : 2u;
|
||||
USBPD_AugmentedPDO_e AugmentedType : 2u; // shall be eUSBPD_APDO_SPR_AVS
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_AUGMENTED
|
||||
} USBPD_SPR_AVS_APDO_t;
|
||||
|
||||
#define SPR_AVS_FMT \
|
||||
"\nSPR AVS Supply:\n" \
|
||||
"\tMax Current 15-20V: %d mA\n" \
|
||||
"\tMax Current 9-15V: %d mA\n" \
|
||||
"\tPeak Current: %d\n"
|
||||
|
||||
#define SPR_AVS_FMT_ARGS( pdo ) \
|
||||
( ( pdo )->SPR_AVS.MaxCurrent15To20VIn10mA * 10 ), ( ( pdo )->SPR_AVS.MaxCurrent9to15VIn10mA * 10 ), \
|
||||
( ( pdo )->SPR_AVS.PeakCurrent )
|
||||
|
||||
typedef union
|
||||
{
|
||||
USBPD_PDOHeader_t Header;
|
||||
USBPD_SourceFixedSupplyPDO_t FixedSupply;
|
||||
USBPD_VariablePDO_t VariableSupply;
|
||||
USBPD_BatteryPDO_t BatterySupply;
|
||||
USBPD_SPR_PPS_APDO_t SPR_PPS;
|
||||
USBPD_EPR_AVS_APDO_t EPR_AVS;
|
||||
USBPD_SPR_AVS_APDO_t SPR_AVS;
|
||||
} USBPD_SourcePDO_t;
|
||||
|
||||
static_assert( sizeof( USBPD_SourcePDO_t ) == sizeof( uint32_t ), "USBPD_SourcePDO_t size mismatch" );
|
||||
|
||||
typedef enum // Do not PACK, messes up alignment
|
||||
{
|
||||
eUSBPD_FAST_ROLE_SWAP_NOT_SUPPORTED = 0,
|
||||
eUSBPD_FAST_ROLE_SWAP_DEFAULT = 1,
|
||||
eUSBPD_FAST_ROLE_SWAP_1A5 = 2, // 1.5A @ 5V
|
||||
eUSBPD_FAST_ROLE_SWAP_3A = 3, // 3A @ 5V
|
||||
} USBPD_FastRoleSwapRequiredCurrent_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t CurrentIn10mA : 10u;
|
||||
uint32_t VoltageIn50mV : 10u;
|
||||
uint32_t Reserved_20_22bit : 3u; // shall be set to zero
|
||||
USBPD_FastRoleSwapRequiredCurrent_e FastRoleSwap : 2u;
|
||||
uint32_t DualRoleData : 1u;
|
||||
uint32_t USBComsCapable : 1u;
|
||||
uint32_t UnconstrainedPower : 1u;
|
||||
uint32_t HigherCapability : 1u;
|
||||
uint32_t DualRolePower : 1u;
|
||||
USBPD_PowerDataObject_e PDOType : 2u; // shall be eUSBPD_PDO_FIXED
|
||||
} USBPD_SinkFixedSupplyPDO_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
USBPD_PDOHeader_t Header;
|
||||
USBPD_SinkFixedSupplyPDO_t FixedSupply;
|
||||
USBPD_VariablePDO_t VariableSupply;
|
||||
USBPD_BatteryPDO_t BatterySupply;
|
||||
USBPD_SPR_PPS_APDO_t SPR_PPS;
|
||||
USBPD_EPR_AVS_APDO_t EPR_AVS;
|
||||
USBPD_SPR_AVS_APDO_t SPR_AVS;
|
||||
} USBPD_SinkPDO_t;
|
||||
|
||||
static_assert( sizeof( USBPD_SourcePDO_t ) == sizeof( uint32_t ), "USBPD_SourcePDO_t size mismatch" );
|
||||
static_assert( sizeof( USBPD_SinkPDO_t ) == sizeof( uint32_t ), "USBPD_SinkPDO_t size mismatch" );
|
||||
|
||||
typedef union
|
||||
{
|
||||
USBPD_SourcePDO_t Source[7];
|
||||
USBPD_SinkPDO_t Sink[7];
|
||||
} USBPD_SPR_CapabilitiesMessage_t;
|
||||
|
||||
static_assert( sizeof( USBPD_SPR_CapabilitiesMessage_t ) == ( 7 * sizeof( uint32_t ) ),
|
||||
"USBPD_SPR_CapabilitiesMessage_t size mismatch" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxCurrentIn10mA : 10u;
|
||||
uint32_t OperatingCurrentIn10mA : 10u;
|
||||
uint32_t Reserved_20_21bit : 2u; // shall be set to zero
|
||||
uint32_t ERPCapable : 1u;
|
||||
uint32_t UnchunkedExtendedMessage : 1u;
|
||||
uint32_t NoUSBSuspended : 1u;
|
||||
uint32_t USBComsCapable : 1u;
|
||||
uint32_t CapabilityMissmatch : 1u;
|
||||
uint32_t Giveback : 1u; // Deprecated, shall be set to zero
|
||||
uint32_t ObjectPosition : 4u; // Reserved and shall not be used
|
||||
} USBPD_FixedAndVariableRDO_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t MaxPowerIn250mW : 10u;
|
||||
uint32_t OperatingPowerIn250mW : 10u;
|
||||
uint32_t Reserved_20_21bit : 2u; // shall be set to zero
|
||||
uint32_t ERPCapable : 1u;
|
||||
uint32_t UnchunkedExtendedMessage : 1u;
|
||||
uint32_t NoUSBSuspended : 1u;
|
||||
uint32_t USBComsCapable : 1u;
|
||||
uint32_t CapabilityMissmatch : 1u;
|
||||
uint32_t Giveback : 1u; // Deprecated, shall be set to zero
|
||||
uint32_t ObjectPosition : 4u; // Reserved and shall not be used
|
||||
} USBPD_BatteryRDO_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t OperatingCurrentIn50mA : 7u;
|
||||
uint32_t Reserved_7_8bit : 2u; // shall be set to zero
|
||||
uint32_t OutputVoltageIn20mV : 12u;
|
||||
uint32_t Reserved_21bit : 1u; // shall be set to zero
|
||||
uint32_t ERPCapable : 1u;
|
||||
uint32_t UnchunkedExtendedMessage : 1u;
|
||||
uint32_t NoUSBSuspended : 1u;
|
||||
uint32_t USBComsCapable : 1u;
|
||||
uint32_t CapabilityMissmatch : 1u;
|
||||
uint32_t Reserved_27bit : 1u; // Deprecated, shall be set to zero
|
||||
uint32_t ObjectPosition : 4u; // Reserved and shall not be used
|
||||
} USBPD_PPS_RDO_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t OperatingCurrentIn50mA : 7u;
|
||||
uint32_t Reserved_7_8bit : 2u; // shall be set to zero
|
||||
uint32_t OutputVoltageIn100mV : 12u; // NOTE: Output voltage in 25mV units, the least two significant bits Shall
|
||||
// be set to zero making the effective voltage step size 100mV.
|
||||
uint32_t Reserved_21bit : 1u; // shall be set to zero
|
||||
uint32_t ERPCapable : 1u;
|
||||
uint32_t UnchunkedExtendedMessage : 1u;
|
||||
uint32_t NoUSBSuspended : 1u;
|
||||
uint32_t USBComsCapable : 1u;
|
||||
uint32_t CapabilityMissmatch : 1u;
|
||||
uint32_t Reserved_27bit : 1u; // Deprecated, shall be set to zero
|
||||
uint32_t ObjectPosition : 4u; // Reserved and shall not be used
|
||||
} USBPD_AVS_RDO_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
USBPD_FixedAndVariableRDO_t FixedAndVariable;
|
||||
USBPD_BatteryRDO_t Battery;
|
||||
USBPD_PPS_RDO_t PPS;
|
||||
} USBPD_RequestDataObject_t;
|
||||
|
||||
static_assert( sizeof( USBPD_RequestDataObject_t ) == sizeof( uint32_t ), "USBPD_RequestDataObject_t size mismatch" );
|
||||
|
||||
// TODO: Define the rest of the message types sections 6.4.3 -> 6.5.16
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eUSBPD_MAX_EXTENDED_MSG_LEN = 260,
|
||||
eUSBPD_MAX_EXTENDED_MSG_CHUNK_LEN = 26,
|
||||
eUSBPD_MAX_EXTENDED_MSG_LEGACY_LEN = 26,
|
||||
} USBPD_ValueParameters_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eUSBPD_OK = 0,
|
||||
eUSBPD_BUSY,
|
||||
eUSBPD_ERROR,
|
||||
eUSBPD_ERROR_ARGS,
|
||||
eUSBPD_ERROR_NOT_SUPPORTED,
|
||||
eUSBPD_ERROR_TIMEOUT,
|
||||
} USBPD_Result_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eUSBPD_VCC_3V3 = 0,
|
||||
eUSBPD_VCC_5V0 = 1,
|
||||
} USBPD_VCC_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eUSBPD_CCNONE = 0,
|
||||
eUSBPD_CC1 = 1,
|
||||
eUSBPD_CC2 = 2,
|
||||
} USBPD_CC_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eSTATE_IDLE,
|
||||
eSTATE_CABLE_DETECT,
|
||||
eSTATE_SOURCE_CAP,
|
||||
eSTATE_WAIT_ACCEPT,
|
||||
eSTATE_WAIT_PS_RDY,
|
||||
eSTATE_PS_RDY,
|
||||
eSTATE_MAX,
|
||||
} USBPD_State_e;
|
||||
|
||||
/**
|
||||
* @brief Initialize the USB PD module
|
||||
* @param vcc: VCC voltage level (3.3V or 5V)
|
||||
* @return USBPD_Result_e
|
||||
*/
|
||||
USBPD_Result_e USBPD_Init( USBPD_VCC_e vcc );
|
||||
|
||||
/**
|
||||
* @brief Negotiate with the USB PD Source, must be called periodically
|
||||
* @param None
|
||||
* @return USBPD_BUSY if negotiation is in progress, eUSBPD_OK if successful, or an error code
|
||||
*/
|
||||
USBPD_Result_e USBPD_SinkNegotiate( void );
|
||||
|
||||
/**
|
||||
* @brief Reset the USB PD module
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void USBPD_Reset( void );
|
||||
|
||||
/**
|
||||
* @brief Get the current state of the USB PD module
|
||||
* @param None
|
||||
* @return USBPD_State_e representing the current state of the module
|
||||
*/
|
||||
USBPD_State_e USBPD_GetState( void );
|
||||
|
||||
/**
|
||||
* @brief Convert USB PD state to string
|
||||
* @param state: USBPD_State_e to convert
|
||||
* @return Pointer to a string representing the state
|
||||
*/
|
||||
const char *USBPD_StateToStr( USBPD_State_e state );
|
||||
|
||||
/**
|
||||
* @brief Convert USB PD result to string
|
||||
* @param result: USBPD_Result_e to convert
|
||||
* @return Pointer to a string representing the result
|
||||
*/
|
||||
const char *USBPD_ResultToStr( USBPD_Result_e result );
|
||||
|
||||
/**
|
||||
* @brief Select a new Power Data Object (PDO) to be used. No re-negotiation is needed.
|
||||
* @param index: Index of the PDO to select (0-based)
|
||||
* @param voltageIn100mV: Desired output voltage in 100mV units (e.g., 500 for 5V) (only applicable for PPS)
|
||||
* @return USBPD_Result_e
|
||||
*/
|
||||
USBPD_Result_e USBPD_SelectPDO( uint8_t index, uint32_t voltageIn100mV );
|
||||
|
||||
/**
|
||||
* @brief Get the capabilities of the USB PD Source
|
||||
* @param[out] capabilities: Pointer to a pointer where the capabilities message structure is stored
|
||||
* @return Number of Power Data Objects (PDOs) in the capabilities message
|
||||
*/
|
||||
size_t USBPD_GetCapabilities( USBPD_SPR_CapabilitiesMessage_t **capabilities );
|
||||
|
||||
/**
|
||||
* @brief Check if the Power Data Object is a Programmable Power Supply (PPS)
|
||||
* @param[in] pdo: Pointer to the Power Data Object to check
|
||||
* @return true if the PDO is a PPS, false otherwise
|
||||
*/
|
||||
bool USBPD_IsPPS( const USBPD_SourcePDO_t *pdo );
|
||||
|
||||
/**
|
||||
* @brief Get the USB PD Specification Revision
|
||||
* @param None
|
||||
* @return USBPD_SpecificationRevision_e representing the USB PD specification revision
|
||||
*/
|
||||
USBPD_SpecificationRevision_e USBPD_GetVersion( void );
|
||||
|
||||
#if defined( USBPD_IMPLEMENTATION )
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ccCount;
|
||||
volatile USBPD_State_e state;
|
||||
USBPD_SpecificationRevision_e pdVersion;
|
||||
USBPD_CC_e lastCCLine;
|
||||
USBPD_SPR_CapabilitiesMessage_t caps;
|
||||
uint8_t messageID;
|
||||
uint8_t pdoCount;
|
||||
bool gotSourceGoodCRC;
|
||||
} USBPD_Instance_t;
|
||||
|
||||
static __attribute__( ( aligned( 4 ) ) ) uint8_t s_buffer[34];
|
||||
static USBPD_Instance_t s_instance = {
|
||||
.pdVersion = eUSBPD_REV_30,
|
||||
};
|
||||
|
||||
static USBPD_CC_e GetActiveCCLine( void );
|
||||
static void SwitchRXMode( void );
|
||||
static void SendMessage( uint8_t size );
|
||||
static void ParsePacket( void );
|
||||
|
||||
USBPD_Result_e USBPD_Init( USBPD_VCC_e vcc )
|
||||
{
|
||||
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO;
|
||||
RCC->AHBPCENR |= RCC_USBPD;
|
||||
|
||||
GPIOC->CFGHR &= ~( 0xf << ( ( 14 & 7 ) << 2 ) );
|
||||
GPIOC->CFGHR |= ( GPIO_Speed_10MHz | GPIO_CNF_OUT_OD ) << ( ( 14 & 7 ) << 2 );
|
||||
GPIOC->CFGHR &= ~( 0xf << ( ( 15 & 7 ) << 2 ) );
|
||||
GPIOC->CFGHR |= ( GPIO_Speed_10MHz | GPIO_CNF_OUT_OD ) << ( ( 15 & 7 ) << 2 );
|
||||
|
||||
AFIO->CTLR |= USBPD_IN_HVT;
|
||||
if ( vcc == eUSBPD_VCC_3V3 )
|
||||
{
|
||||
AFIO->CTLR |= USBPD_PHY_V33;
|
||||
}
|
||||
|
||||
USBPD->DMA = (uint32_t)s_buffer;
|
||||
USBPD->CONFIG = IE_RX_ACT | IE_RX_RESET | IE_TX_END | PD_DMA_EN | PD_FILT_EN;
|
||||
USBPD->STATUS = BUF_ERR | IF_RX_BIT | IF_RX_BYTE | IF_RX_ACT | IF_RX_RESET | IF_TX_END;
|
||||
|
||||
// disable CC comparators
|
||||
USBPD->PORT_CC1 &= ~( CC_CMP_MASK | PA_CC_AI );
|
||||
USBPD->PORT_CC2 &= ~( CC_CMP_MASK | PA_CC_AI );
|
||||
// set CC comparator voltage
|
||||
USBPD->PORT_CC1 |= CC_CMP_66;
|
||||
USBPD->PORT_CC2 |= CC_CMP_66;
|
||||
|
||||
return eUSBPD_OK;
|
||||
}
|
||||
|
||||
USBPD_Result_e USBPD_SinkNegotiate( void )
|
||||
{
|
||||
switch ( s_instance.state )
|
||||
{
|
||||
case eSTATE_IDLE:;
|
||||
const uint8_t ccLine = GetActiveCCLine();
|
||||
if ( ccLine == eUSBPD_CCNONE )
|
||||
{
|
||||
s_instance.ccCount = 0;
|
||||
s_instance.lastCCLine = eUSBPD_CCNONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( s_instance.lastCCLine != ccLine )
|
||||
{
|
||||
s_instance.lastCCLine = ccLine;
|
||||
s_instance.ccCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_instance.ccCount++;
|
||||
}
|
||||
|
||||
if ( s_instance.ccCount > 10 )
|
||||
{
|
||||
if ( ccLine == eUSBPD_CC2 )
|
||||
{
|
||||
USBPD->CONFIG |= CC_SEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBPD->CONFIG &= ~CC_SEL;
|
||||
}
|
||||
|
||||
s_instance.ccCount = 0;
|
||||
s_instance.state = eSTATE_CABLE_DETECT;
|
||||
|
||||
SwitchRXMode();
|
||||
// NVIC_SetPriority(USBPD_IRQn, 0x00); // TODO: Is this needed?
|
||||
NVIC_EnableIRQ( USBPD_IRQn );
|
||||
}
|
||||
break;
|
||||
|
||||
case eSTATE_SOURCE_CAP:
|
||||
USBPD_SelectPDO( 0, 0 ); // Select the first PDO by default
|
||||
s_instance.state = eSTATE_WAIT_ACCEPT;
|
||||
break;
|
||||
|
||||
case eSTATE_PS_RDY: return eUSBPD_OK;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return eUSBPD_BUSY;
|
||||
}
|
||||
|
||||
void USBPD_Reset( void )
|
||||
{
|
||||
NVIC_DisableIRQ( USBPD_IRQn );
|
||||
s_instance = ( USBPD_Instance_t ){
|
||||
.pdVersion = eUSBPD_REV_30,
|
||||
};
|
||||
}
|
||||
|
||||
USBPD_State_e USBPD_GetState( void )
|
||||
{
|
||||
return s_instance.state;
|
||||
}
|
||||
|
||||
#if FUNCONF_USBPD_NO_STR
|
||||
const char *USBPD_StateToStr( USBPD_State_e state )
|
||||
{
|
||||
(void)state;
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *USBPD_ResultToStr( USBPD_Result_e result )
|
||||
{
|
||||
(void)result;
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
const char *USBPD_StateToStr( USBPD_State_e state )
|
||||
{
|
||||
switch ( state )
|
||||
{
|
||||
case eSTATE_IDLE: return "Idle";
|
||||
case eSTATE_CABLE_DETECT: return "Cable Detected";
|
||||
case eSTATE_SOURCE_CAP: return "Got Source Capabilities";
|
||||
case eSTATE_WAIT_ACCEPT: return "Waiting for Accept";
|
||||
case eSTATE_WAIT_PS_RDY: return "Waiting for PS_Ready";
|
||||
case eSTATE_PS_RDY: return "Power Supply Ready";
|
||||
default: return "Unknown State";
|
||||
}
|
||||
};
|
||||
|
||||
const char *USBPD_ResultToStr( USBPD_Result_e result )
|
||||
{
|
||||
switch ( result )
|
||||
{
|
||||
case eUSBPD_OK: return "OK";
|
||||
case eUSBPD_BUSY: return "Busy";
|
||||
case eUSBPD_ERROR: return "Error";
|
||||
case eUSBPD_ERROR_ARGS: return "Error Args";
|
||||
case eUSBPD_ERROR_NOT_SUPPORTED: return "Error Not Supported";
|
||||
case eUSBPD_ERROR_TIMEOUT: return "Error Timeout";
|
||||
default: return "Unknown Result";
|
||||
}
|
||||
}
|
||||
#endif // FUNCONF_USBPD_NO_STR
|
||||
|
||||
USBPD_Result_e USBPD_SelectPDO( uint8_t index, uint32_t voltageIn100mV )
|
||||
{
|
||||
if ( index >= s_instance.pdoCount )
|
||||
{
|
||||
return eUSBPD_ERROR_ARGS;
|
||||
}
|
||||
|
||||
const USBPD_SourcePDO_t *const pdo = &s_instance.caps.Source[index];
|
||||
|
||||
*(USBPD_MessageHeader_t *)&s_buffer[0] = ( USBPD_MessageHeader_t ){
|
||||
.MessageID = s_instance.messageID,
|
||||
.MessageType = eUSBPD_DATA_MSG_REQUEST,
|
||||
.NumberOfDataObjects = 1u,
|
||||
.SpecificationRevision = s_instance.pdVersion,
|
||||
};
|
||||
USBPD_RequestDataObject_t *const rdo = (USBPD_RequestDataObject_t *)&s_buffer[sizeof( USBPD_MessageHeader_t )];
|
||||
|
||||
if ( USBPD_IsPPS( pdo ) )
|
||||
{
|
||||
// Clamp voltage to min/max NOTE: Maybe we should return an error if the voltage is out of range?
|
||||
const uint32_t minVoltage = pdo->SPR_PPS.MinVoltageIn100mV;
|
||||
const uint32_t maxVoltage = pdo->SPR_PPS.MaxVoltageIn100mV;
|
||||
voltageIn100mV = voltageIn100mV > maxVoltage ? maxVoltage : voltageIn100mV;
|
||||
voltageIn100mV = voltageIn100mV < minVoltage ? minVoltage : voltageIn100mV;
|
||||
|
||||
*rdo = ( USBPD_RequestDataObject_t ){
|
||||
.PPS =
|
||||
{
|
||||
.ObjectPosition = index + 1,
|
||||
.OutputVoltageIn20mV = voltageIn100mV * 5,
|
||||
.OperatingCurrentIn50mA = pdo->SPR_PPS.MaxCurrentIn50mA,
|
||||
.NoUSBSuspended = 1u,
|
||||
.USBComsCapable = 1u, // TODO: Should have these are arguments or define
|
||||
},
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
*rdo = ( USBPD_RequestDataObject_t ){
|
||||
.FixedAndVariable =
|
||||
{
|
||||
.ObjectPosition = index + 1,
|
||||
.MaxCurrentIn10mA = pdo->FixedSupply.MaxCurrentIn10mA,
|
||||
.OperatingCurrentIn10mA = pdo->FixedSupply.MaxCurrentIn10mA,
|
||||
.USBComsCapable = 1u,
|
||||
.NoUSBSuspended = 1u,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
SendMessage( 6 );
|
||||
|
||||
return eUSBPD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the capabilities of the USB PD Source
|
||||
* @param[out] capabilities: pointer to the capabilities message structure
|
||||
* @return Number of Power Data Objects (PDOs) in the capabilities message
|
||||
*/
|
||||
size_t USBPD_GetCapabilities( USBPD_SPR_CapabilitiesMessage_t **capabilities )
|
||||
{
|
||||
if ( s_instance.pdoCount == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( capabilities )
|
||||
{
|
||||
*capabilities = &s_instance.caps;
|
||||
}
|
||||
|
||||
return s_instance.pdoCount;
|
||||
}
|
||||
|
||||
bool USBPD_IsPPS( const USBPD_SourcePDO_t *pdo )
|
||||
{
|
||||
return ( pdo->Header.PDOType == eUSBPD_PDO_AUGMENTED ) && ( pdo->Header.AugmentedType == eUSBPD_APDO_SPR_PPS );
|
||||
}
|
||||
|
||||
USBPD_SpecificationRevision_e USBPD_GetVersion( void )
|
||||
{
|
||||
return s_instance.pdVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check CC line status
|
||||
* @param None
|
||||
* @return USBPD_CC_t
|
||||
*/
|
||||
static USBPD_CC_e GetActiveCCLine( void )
|
||||
{
|
||||
// Switch to CC1
|
||||
USBPD->CONFIG &= ~CC_SEL;
|
||||
Delay_Us( 1 );
|
||||
// check if CC1 is connected
|
||||
if ( USBPD->PORT_CC1 & PA_CC_AI )
|
||||
{
|
||||
return eUSBPD_CC1;
|
||||
}
|
||||
|
||||
// Switch to CC2
|
||||
USBPD->CONFIG |= CC_SEL;
|
||||
Delay_Us( 1 );
|
||||
if ( USBPD->PORT_CC2 & PA_CC_AI )
|
||||
{
|
||||
return eUSBPD_CC2;
|
||||
}
|
||||
|
||||
return eUSBPD_CCNONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switch to RX mode
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
static void SwitchRXMode( void )
|
||||
{
|
||||
USBPD->BMC_CLK_CNT = UPD_TMR_RX;
|
||||
USBPD->CONTROL = ( USBPD->CONTROL & ~PD_TX_EN ) | BMC_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin transmission of PD message
|
||||
* @param size: size of the message in bytes
|
||||
* @return None
|
||||
*/
|
||||
static void SendMessage( uint8_t size )
|
||||
{
|
||||
USBPD->BMC_CLK_CNT = UPD_TMR_TX;
|
||||
USBPD->TX_SEL = UPD_SOP0;
|
||||
USBPD->BMC_TX_SZ = size;
|
||||
USBPD->STATUS = 0;
|
||||
USBPD->CONTROL |= BMC_START | PD_TX_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse the received packet
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
static void ParsePacket( void )
|
||||
{
|
||||
bool sendGoodCRC = true;
|
||||
USBPD_MessageHeader_t message = *(USBPD_MessageHeader_t *)s_buffer;
|
||||
|
||||
USBPD_State_e nextState = s_instance.state;
|
||||
|
||||
if ( message.NumberOfDataObjects == 0u )
|
||||
{
|
||||
switch ( (USBPD_ControlMessage_e)message.MessageType )
|
||||
{
|
||||
case eUSBPD_CTRL_MSG_GOODCRC:
|
||||
sendGoodCRC = false;
|
||||
s_instance.messageID++;
|
||||
break;
|
||||
|
||||
case eUSBPD_CTRL_MSG_ACCEPT: nextState = eSTATE_WAIT_PS_RDY; break;
|
||||
|
||||
case eUSBPD_CTRL_MSG_REJECT: nextState = eSTATE_SOURCE_CAP; break;
|
||||
|
||||
case eUSBPD_CTRL_MSG_PS_RDY: nextState = eSTATE_PS_RDY; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( (USBPD_DataMessage_e)message.MessageType )
|
||||
{
|
||||
|
||||
case eUSBPD_DATA_MSG_SOURCE_CAP:
|
||||
nextState = eSTATE_SOURCE_CAP;
|
||||
s_instance.pdoCount = message.NumberOfDataObjects;
|
||||
s_instance.pdVersion = message.SpecificationRevision;
|
||||
memcpy( &s_instance.caps, &s_buffer[2], sizeof( USBPD_SPR_CapabilitiesMessage_t ) );
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( message.Extended || sendGoodCRC )
|
||||
{
|
||||
Delay_Us( 30 );
|
||||
USBPD_ControlMessage_t reply = ( USBPD_ControlMessage_t ){
|
||||
.MessageID = message.MessageID,
|
||||
.MessageType = eUSBPD_CTRL_MSG_GOODCRC,
|
||||
.SpecificationRevision = s_instance.pdVersion,
|
||||
};
|
||||
*(uint16_t *)&s_buffer[0] = reply.data;
|
||||
SendMessage( sizeof( reply ) );
|
||||
}
|
||||
|
||||
s_instance.state = nextState;
|
||||
}
|
||||
|
||||
void USBPD_IRQHandler( void ) __attribute__( ( interrupt ) );
|
||||
void USBPD_IRQHandler( void )
|
||||
{
|
||||
// Receive complete interrupt
|
||||
if ( USBPD->STATUS & IF_RX_ACT )
|
||||
{
|
||||
// Check if we received a SOP0 packet
|
||||
if ( ( ( USBPD->STATUS & BMC_AUX_MASK ) == BMC_AUX_SOP0 ) && ( USBPD->BMC_BYTE_CNT >= 6 ) )
|
||||
{
|
||||
ParsePacket();
|
||||
}
|
||||
USBPD->STATUS |= IF_RX_ACT;
|
||||
}
|
||||
|
||||
// Transmit complete interrupt (GoodCRC only)
|
||||
if ( USBPD->STATUS & IF_TX_END )
|
||||
{
|
||||
SwitchRXMode();
|
||||
USBPD->STATUS |= IF_TX_END;
|
||||
}
|
||||
|
||||
// Reset interrupt
|
||||
if ( USBPD->STATUS & IF_RX_RESET )
|
||||
{
|
||||
USBPD->STATUS |= IF_RX_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
4
hw/.gitignore
vendored
4
hw/.gitignore
vendored
@ -39,3 +39,7 @@ fp-info-cache
|
||||
|
||||
# Local project settings
|
||||
*.kicad_prl
|
||||
.history
|
||||
|
||||
# fabrication toolkit output
|
||||
production
|
||||
|
||||
@ -1,29 +1,28 @@
|
||||
Index,LCSC#,MPN,Manufacturer,Package,Customer #,Description,RoHS,Quantity,MOQ,Multiple,Unit Price(€),Extended Price(€),Product Link
|
||||
1,C473369,TLV333IDBVR,TI,SOT-23-5,,"2uV Rail-to-Rail Input, Rail-to-Rail Output 70pA 0.16V/us 102dB 17uA 350kHz 1 SOT-23-5 Amplifiers RoHS",yes,5,5,5,0.2047,1.02,https://www.lcsc.com/product-detail/C473369.html
|
||||
2,C2827931,SS24L,Guangdong Hottech,SOD-123FL,,Diode Independent 40V 2A Surface Mount SOD-123FL,yes,20,20,20,0.0214,0.43,https://www.lcsc.com/product-detail/C2827931.html
|
||||
1,C473369,TLV333IDBVR,TI,SOT-23-5,,"2uV Rail-to-Rail Input, Rail-to-Rail Output 70pA 0.16V/us 102dB 17uA 350kHz 1 SOT-23-5 Amplifiers RoHS",yes,5,5,5,0.2121,1.06,https://www.lcsc.com/product-detail/C473369.html
|
||||
2,C2827931,SS24L,Guangdong Hottech,SOD-123FL,,Diode Independent 40V 2A Surface Mount SOD-123FL,yes,20,20,20,0.0204,0.41,https://www.lcsc.com/product-detail/C2827931.html
|
||||
3,C2931472,U263-163N-4OS1735,XKB Connection,SMD,,USB-C (USB TYPE-C) Receptacle Connector 16 Position Surface Mount,yes,5,5,5,0.2518,1.26,https://www.lcsc.com/product-detail/C2931472.html
|
||||
4,C2999960,MM5Z3V3,Slkor,SOD-523,,Zener Diode Independent 3.3V 200mW Surface Mount SOD-523,yes,20,20,20,0.0180,0.36,https://www.lcsc.com/product-detail/C2999960.html
|
||||
5,C52754543,RB521S30T1G-HXY,HXY MOSFET,SOD-523,,1A 1 Independent 30V 350mV@10mA 200mA SOD-523 Single Diodes RoHS,yes,20,20,20,0.0212,0.42,https://www.lcsc.com/product-detail/C52754543.html
|
||||
5,C52754543,RB521S30T1G-HXY,HXY MOSFET,SOD-523,,1A 1 Independent 30V 350mV@10mA 200mA SOD-523 Single Diodes RoHS,yes,20,20,20,0.0202,0.40,https://www.lcsc.com/product-detail/C52754543.html
|
||||
6,C42442062,CH32X035F8U6,WCH,QFN-20-EP(3x3),,QFN-20-EP(3x3) Microcontrollers RoHS,yes,5,1,1,0.4460,2.23,https://www.lcsc.com/product-detail/C42442062.html
|
||||
7,C780769,AP63203WU-7,DIODES,TSOT-23-6,,1.1MHz Buck Fixed 2A 3.3V TSOT-23-6 Voltage Regulators - DC DC Switching Regulators RoHS,yes,5,1,1,0.3955,1.98,https://www.lcsc.com/product-detail/C780769.html
|
||||
8,C7466527,AGM403AP,AGMSEMI,PDFN3.3x3.3-8,,N-Channel 40V 65A 69W Surface Mount PDFN3.3x3.3,yes,5,5,5,0.2575,1.29,https://www.lcsc.com/product-detail/C7466527.html
|
||||
7,C780769,AP63203WU-7,DIODES,TSOT-23-6,,1.1MHz Buck Fixed 2A 3.3V 3.8V~32V TSOT-23-6 Voltage Regulators - DC DC Switching Regulators RoHS,yes,5,1,1,0.3766,1.88,https://www.lcsc.com/product-detail/C780769.html
|
||||
8,C7466527,AGM403AP,AGMSEMI,PDFN3.3x3.3-8,,N-Channel 40V 65A 69W Surface Mount PDFN3.3x3.3,yes,5,5,5,0.2447,1.22,https://www.lcsc.com/product-detail/C7466527.html
|
||||
9,C2906999,FRC0603F1803TS,FOJAN,0603,,180kΩ ±1% 100mW 0603 Thick Film Resistor,yes,100,100,100,0.0010,0.10,https://www.lcsc.com/product-detail/C2906999.html
|
||||
10,C4169844,RS73F1JTTD2703B,KOA,0603,,200mW 270kΩ Thick Film Resistor ±25ppm/℃ ±0.1% 0603 Chip Resistor - Surface Mount RoHS,yes,5,5,5,0.0638,0.32,https://www.lcsc.com/product-detail/C4169844.html
|
||||
11,C2932326,MT3608L,XI'AN Aerosemi Tech,SOT-23-6,,1.2MHz Boost Adjustable 2.5A SOT-23-6 Voltage Regulators - DC DC Switching Regulators RoHS,yes,10,10,10,0.0373,0.37,https://www.lcsc.com/product-detail/C2932326.html
|
||||
12,C138714,TPD4E05U06DQAR,TI,USON-10(1x2.5),,14VC Clamp 2.5A@8/20us Ipp TVS DIODE USON-10(1x2.5),yes,5,5,5,0.0629,0.31,https://www.lcsc.com/product-detail/C138714.html
|
||||
11,C2932326,MT3608L,XI'AN Aerosemi Tech,SOT-23-6,,1.2MHz Boost Adjustable 2.2V~16V 2.5A SOT-23-6 Voltage Regulators - DC DC Switching Regulators RoHS,yes,10,10,10,0.0373,0.37,https://www.lcsc.com/product-detail/C2932326.html
|
||||
12,C138714,TPD4E05U06DQAR,TI,USON-10(1x2.5),,14VC Clamp 2.5A@8/20us Ipp TVS DIODE USON-10(1x2.5),yes,5,5,5,0.0679,0.34,https://www.lcsc.com/product-detail/C138714.html
|
||||
13,C19274408,SC7A20HTR,Hangzhou Silan Microelectronics,LGA-12(2x2),,LGA-12(2x2) Accelerometers RoHS,yes,5,1,1,0.2417,1.21,https://www.lcsc.com/product-detail/C19274408.html
|
||||
14,C52741377,CPN201610H6R8MT,Magnetsyc,0806,,820mA 6.8uH 1.1A 545mΩ ±20% 0806 Fixed Inductors RoHS,yes,20,20,20,0.0277,0.55,https://www.lcsc.com/product-detail/C52741377.html
|
||||
15,C18723015,X087-2832TSWIG02-H14,Wisevision,-,,"0.87 128x32 SSD1312 chip I2C LCD, OLED, Graphic RoHS",yes,5,1,1,1.6435,8.22,https://www.lcsc.com/product-detail/C18723015.html
|
||||
16,C110776,RT0603BRD071KL,YAGEO,0603,,100mW 1kΩ 75V Thin Film Resistor ±25ppm/℃ ±0.1% 0603 Chip Resistor - Surface Mount RoHS,yes,20,20,20,0.0187,0.37,https://www.lcsc.com/product-detail/C110776.html
|
||||
17,C162670,NCU18XH103F6SRB,muRata,0603,,NTC Thermistor 10kΩ Surface Mount 0603,yes,10,10,10,0.0533,0.53,https://www.lcsc.com/product-detail/C162670.html
|
||||
18,C46818248,SIQ-02FVS3,LZG,-,,Encoders - Industrial RoHS,yes,5,1,1,0.9816,4.91,https://www.lcsc.com/product-detail/C46818248.html
|
||||
19,C41414522,NSG10752,WXNSIC,SOT-23-6,,High Side Gate Driver IC MOSFET IGBT SOT-23-6,yes,5,1,1,0.4842,2.42,https://www.lcsc.com/product-detail/C41414522.html
|
||||
20,C76799,MLZ1608M4R7WT000,TDK,0603,,350mA 4.7uH 120mA 500mΩ Multilayer inductor ±20% 0603 Fixed Inductors RoHS,yes,10,10,10,0.0341,0.34,https://www.lcsc.com/product-detail/C76799.html
|
||||
21,C98192,CL21A475KBQNNNE,Samsung Electro-Mechanics,0805,,4.7uF ±10% 50V Ceramic Capacitor X5R 0805,yes,10,10,10,0.0179,0.18,https://www.lcsc.com/product-detail/C98192.html
|
||||
22,C29936,CL10B105KA8NNNC,Samsung Electro-Mechanics,0603,,1uF ±10% 25V Ceramic Capacitor X7R 0603,yes,50,50,50,0.0056,0.28,https://www.lcsc.com/product-detail/C29936.html
|
||||
23,C1590,CL10B104KA8NNNC,Samsung Electro-Mechanics,0603,,100nF ±10% 25V Ceramic Capacitor X7R 0603,yes,100,100,100,0.0032,0.32,https://www.lcsc.com/product-detail/C1590.html
|
||||
24,C2997487,MPD220M1VD19040R,Ymin,"SMD,7.3x4.3mm",,"35V 22uF 3.2A@100kHz 40mΩ@100kHz ±20% SMD,7.3x4.3mm Aluminum - Polymer Capacitors RoHS",yes,5,1,1,0.7063,3.53,https://www.lcsc.com/product-detail/C2997487.html
|
||||
25,C5796173,MCASU32MAB7106KPNA01,Taiyo Yuden,1210,,10uF ±10% 50V Ceramic Capacitor X7R 1210,yes,25,5,5,0.0982,2.46,https://www.lcsc.com/product-detail/C5796173.html
|
||||
26,C5370906,FC-ALX 4030D-2R2MT,FANGCHENG,"SMD,4.2x4.2mm",,"8.1A 2.2uH 8.1A 10.7mΩ Molded Inductor ±20% SMD,4.2x4.2mm Fixed Inductors RoHS",yes,5,1,1,0.4781,2.39,https://www.lcsc.com/product-detail/C5370906.html
|
||||
27,C49851,INA226AIDGSR,TI,MSOP-10,,300mV~40V 2.5uV 10nA MSOP-10 Current Regulation/Management RoHS,yes,5,1,1,0.5765,2.88,https://www.lcsc.com/product-detail/C49851.html
|
||||
28,C49164932,JER1206F1R002,JIERR,1206,,1W 2mΩ ±50ppm/℃ Current Sense Resistor ±1% 1206 Current Sense Resistors RoHS,yes,10,10,10,0.0371,0.37,https://www.lcsc.com/product-detail/C49164932.html
|
||||
15,C110776,RT0603BRD071KL,YAGEO,0603,,100mW 1kΩ 75V Thin Film Resistor ±25ppm/℃ ±0.1% 0603 Chip Resistor - Surface Mount RoHS,yes,20,20,20,0.0187,0.37,https://www.lcsc.com/product-detail/C110776.html
|
||||
16,C162670,NCU18XH103F6SRB,muRata,0603,,NTC Thermistor 10kΩ Surface Mount 0603,yes,10,10,10,0.0533,0.53,https://www.lcsc.com/product-detail/C162670.html
|
||||
17,C46818248,SIQ-02FVS3,LZG,-,,Encoders - Industrial RoHS,yes,5,1,1,0.9816,4.91,https://www.lcsc.com/product-detail/C46818248.html
|
||||
18,C41414522,NSG10752,WXNSIC,SOT-23-6,,High Side Gate Driver IC MOSFET IGBT SOT-23-6,yes,5,1,1,0.4600,2.30,https://www.lcsc.com/product-detail/C41414522.html
|
||||
19,C76799,MLZ1608M4R7WT000,TDK,0603,,350mA 4.7uH 120mA 500mΩ Multilayer inductor ±20% 0603 Fixed Inductors RoHS,yes,10,10,10,0.0341,0.34,https://www.lcsc.com/product-detail/C76799.html
|
||||
20,C98192,CL21A475KBQNNNE,Samsung Electro-Mechanics,0805,,4.7uF ±10% 50V Ceramic Capacitor X5R 0805,yes,10,10,10,0.0179,0.18,https://www.lcsc.com/product-detail/C98192.html
|
||||
21,C29936,CL10B105KA8NNNC,Samsung Electro-Mechanics,0603,,1uF ±10% 25V Ceramic Capacitor X7R 0603,yes,50,50,50,0.0056,0.28,https://www.lcsc.com/product-detail/C29936.html
|
||||
22,C2997487,MPD220M1VD19040R,Ymin,"SMD,7.3x4.3mm",,"35V 22uF 3.2A@100kHz 40mΩ@100kHz ±20% SMD,7.3x4.3mm Aluminum - Polymer Capacitors RoHS",yes,5,1,1,0.7063,3.53,https://www.lcsc.com/product-detail/C2997487.html
|
||||
23,C5370906,FC-ALX 4030D-2R2MT,FANGCHENG,"SMD,4.2x4.2mm",,"8.1A 2.2uH 8.1A 10.7mΩ Molded Inductor ±20% SMD,4.2x4.2mm Fixed Inductors RoHS",yes,5,1,1,0.4781,2.39,https://www.lcsc.com/product-detail/C5370906.html
|
||||
24,C18723014,X069-9616TSWIG02-H14,Wisevision,-,,"0.69 96x16 SSD1312 chip I2C LCD, OLED, Graphic RoHS",yes,2,1,1,1.3337,2.67,https://www.lcsc.com/product-detail/C18723014.html
|
||||
25,C386166,UMK325AB7106KMHP,Taiyo Yuden,1210,,10uF ±10% 50V Ceramic Capacitor X7R 1210 AEC-Q200,yes,25,5,5,0.0854,2.14,https://www.lcsc.com/product-detail/C386166.html
|
||||
26,C38582720,TPA191A4-SC6R,3PEAK,SOT-363,,50uV -300mV~+36V 22uA 2.5V/us 120dB 30kHz 80uA 100V/V SOT-363 Amplifiers RoHS,yes,5,5,5,0.5300,2.65,https://www.lcsc.com/product-detail/C38582720.html
|
||||
27,C5185587,CUM1206-15FR004,FORT,1206,,1W 4mΩ SMD ±50ppm/℃ Current Sense Resistor ±1% 1206 Current Sense Resistors RoHS,yes,5,1,1,0.0157,0.08,https://www.lcsc.com/product-detail/C5185587.html
|
||||
|
||||
|
28
hw/bom/order_1.csv
Normal file
28
hw/bom/order_1.csv
Normal file
@ -0,0 +1,28 @@
|
||||
LCSC Part Number,Manufacture Part Number,Manufacturer,Customer NO.,Package,Description,RoHS,Quantity,Unit Price(€),Ext.Price(€),Estimated lead time (business days),Date Code / Lot No.
|
||||
C473369,TLV333IDBVR,TI,,SOT-23-5,"2uV Rail-to-Rail Input, Rail-to-Rail Output 70pA 0.16V/us 102dB 17uA 350kHz 1 SOT-23-5 Amplifiers RoHS",YES,5,0.2121,1.06,,
|
||||
C2827931,SS24L,Guangdong Hottech,,SOD-123FL,Diode Independent 40V 2A Surface Mount SOD-123FL,YES,20,0.0214,0.43,,
|
||||
C2931472,U263-163N-4OS1735,XKB Connection,,SMD,USB-C (USB TYPE-C) Receptacle Connector 16 Position Surface Mount,YES,5,0.2518,1.26,,
|
||||
C2999960,MM5Z3V3,Slkor,,SOD-523,Zener Diode Independent 3.3V 200mW Surface Mount SOD-523,YES,20,0.0181,0.36,,
|
||||
C52754543,RB521S30T1G-HXY,HXY MOSFET,,SOD-523,1A 1 Independent 30V 350mV@10mA 200mA SOD-523 Single Diodes RoHS,YES,20,0.0212,0.42,,
|
||||
C42442062,CH32X035F8U6,WCH,,QFN-20-EP(3x3),QFN-20-EP(3x3) Microcontrollers RoHS,YES,5,0.446,2.23,,
|
||||
C780769,AP63203WU-7,DIODES,,TSOT-23-6,1.1MHz Buck Fixed 2A 3.3V 3.8V~32V TSOT-23-6 Voltage Regulators - DC DC Switching Regulators RoHS,YES,5,0.3766,1.88,,
|
||||
C7466527,AGM403AP,AGMSEMI,,PDFN3.3x3.3-8,N-Channel 40V 65A 69W Surface Mount PDFN3.3x3.3,YES,5,0.2575,1.29,,
|
||||
C2906999,FRC0603F1803TS,FOJAN,,0603,180kΩ ±1% 100mW 0603 Thick Film Resistor,YES,100,0.001,0.10,,
|
||||
C4169844,RS73F1JTTD2703B,KOA,,0603,200mW 270kΩ Thick Film Resistor ±25ppm/℃ ±0.1% 0603 Chip Resistor - Surface Mount RoHS,YES,5,0.0638,0.32,,
|
||||
C2932326,MT3608L,XI'AN Aerosemi Tech,,SOT-23-6,1.2MHz Boost Adjustable 2.2V~16V 2.5A SOT-23-6 Voltage Regulators - DC DC Switching Regulators RoHS,YES,10,0.0373,0.37,,
|
||||
C138714,TPD4E05U06DQAR,TI,,USON-10(1x2.5),14VC Clamp 2.5A@8/20us Ipp TVS DIODE USON-10(1x2.5),YES,5,0.0682,0.34,,
|
||||
C19274408,SC7A20HTR,Hangzhou Silan Microelectronics,,LGA-12(2x2),LGA-12(2x2) Accelerometers RoHS,YES,5,0.2417,1.21,,
|
||||
C52741377,CPN201610H6R8MT,Magnetsyc,,0806,820mA 6.8uH 1.1A 545mΩ ±20% 0806 Fixed Inductors RoHS,YES,20,0.0277,0.55,,
|
||||
C110776,RT0603BRD071KL,YAGEO,,0603,100mW 1kΩ 75V Thin Film Resistor ±25ppm/℃ ±0.1% 0603 Chip Resistor - Surface Mount RoHS,YES,20,0.0187,0.37,,
|
||||
C162670,NCU18XH103F6SRB,muRata,,0603,NTC Thermistor 10kΩ Surface Mount 0603,YES,10,0.0533,0.53,,
|
||||
C46818248,SIQ-02FVS3,LZG,,-,Encoders - Industrial RoHS,YES,5,0.9816,4.91,,
|
||||
C41414522,NSG10752,WXNSIC,,SOT-23-6,High Side Gate Driver IC MOSFET IGBT SOT-23-6,YES,5,0.4842,2.42,,
|
||||
C76799,MLZ1608M4R7WT000,TDK,,0603,350mA 4.7uH 120mA 500mΩ Multilayer inductor ±20% 0603 Fixed Inductors RoHS,YES,10,0.0351,0.35,,
|
||||
C98192,CL21A475KBQNNNE,Samsung Electro-Mechanics,,0805,4.7uF ±10% 50V Ceramic Capacitor X5R 0805,YES,10,0.0179,0.18,,
|
||||
C29936,CL10B105KA8NNNC,Samsung Electro-Mechanics,,0603,1uF ±10% 25V Ceramic Capacitor X7R 0603,YES,50,0.0056,0.28,,
|
||||
C2997487,MPD220M1VD19040R,Ymin,,"SMD,7.3x4.3mm","35V 22uF 3.2A@100kHz 40mΩ@100kHz ±20% SMD,7.3x4.3mm Aluminum - Polymer Capacitors RoHS",YES,5,0.7063,3.53,,
|
||||
C5370906,FC-ALX 4030D-2R2MT,FANGCHENG,,"SMD,4.2x4.2mm","8.1A 2.2uH 8.1A 10.7mΩ Molded Inductor ±20% SMD,4.2x4.2mm Fixed Inductors RoHS",YES,5,0.4781,2.39,,
|
||||
C18723014,X069-9616TSWIG02-H14,Wisevision,,-,"0.69 96x16 SSD1312 chip I2C LCD, OLED, Graphic RoHS",YES,2,1.3337,2.67,,
|
||||
C386166,UMK325AB7106KMHP,Taiyo Yuden,,1210,10uF ±10% 50V Ceramic Capacitor X7R 1210 AEC-Q200,YES,25,0.0854,2.14,,
|
||||
C38582720,TPA191A4-SC6R,3PEAK,,SOT-363,50uV -300mV~+36V 22uA 2.5V/us 120dB 30kHz 80uA 100V/V SOT-363 Amplifiers RoHS,YES,5,0.53,2.65,,
|
||||
C5185587,CUM1206-15FR004,FORT,,1206,1W 4mΩ SMD ±50ppm/℃ Current Sense Resistor ±1% 1206 Current Sense Resistors RoHS,YES,5,0.0522,0.26,,
|
||||
|
1
hw/fabrication-toolkit-options.json
Normal file
1
hw/fabrication-toolkit-options.json
Normal file
@ -0,0 +1 @@
|
||||
{"ARCHIVE_NAME": "", "EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false, "OPEN BROWSER": true, "NO_BACKUP_OPT": false}
|
||||
@ -434,6 +434,12 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(pad "A1" smd rect
|
||||
(at -3.2 -2.4775)
|
||||
(size 0.5 1.15)
|
||||
(layers "F.Cu" "F.Mask" "F.Paste")
|
||||
(uuid "ea8dadf2-8afa-4fe2-9e30-22206c244069")
|
||||
)
|
||||
(pad "A4" smd rect
|
||||
(at -2.4 -2.4775)
|
||||
(size 0.5 1.15)
|
||||
@ -464,6 +470,12 @@
|
||||
(layers "F.Cu" "F.Mask" "F.Paste")
|
||||
(uuid "a621d7b8-8475-4012-bb80-22970594526c")
|
||||
)
|
||||
(pad "B1" smd rect
|
||||
(at 3.2185 -2.4775)
|
||||
(size 0.5 1.15)
|
||||
(layers "F.Cu" "F.Mask" "F.Paste")
|
||||
(uuid "b6f3c56c-8cda-4c18-83e9-de8afa037a13")
|
||||
)
|
||||
(pad "B4" smd rect
|
||||
(at 2.4 -2.4775)
|
||||
(size 0.5 1.15)
|
||||
@ -494,18 +506,6 @@
|
||||
(layers "F.Cu" "F.Mask" "F.Paste")
|
||||
(uuid "b669d7b8-13ce-4926-b0fa-a776cf6d1e07")
|
||||
)
|
||||
(pad "GND" smd rect
|
||||
(at -3.2 -2.4775)
|
||||
(size 0.5 1.15)
|
||||
(layers "F.Cu" "F.Mask" "F.Paste")
|
||||
(uuid "ea8dadf2-8afa-4fe2-9e30-22206c244069")
|
||||
)
|
||||
(pad "GND" smd rect
|
||||
(at 3.2185 -2.4775)
|
||||
(size 0.5 1.15)
|
||||
(layers "F.Cu" "F.Mask" "F.Paste")
|
||||
(uuid "b6f3c56c-8cda-4c18-83e9-de8afa037a13")
|
||||
)
|
||||
(pad "S1" thru_hole oval
|
||||
(at -4.32 -1.8025)
|
||||
(size 1.2 2.2)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,8 @@
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_barcodes": false,
|
||||
"apply_defaults_to_fp_dimensions": false,
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
@ -48,7 +50,7 @@
|
||||
"silk_text_thickness": 0.1,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"min_clearance": 0.25
|
||||
"min_clearance": 0.2
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
@ -77,6 +79,7 @@
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_filters_mismatch": "ignore",
|
||||
"footprint_symbol_field_mismatch": "warning",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "ignore",
|
||||
"hole_clearance": "error",
|
||||
@ -94,6 +97,7 @@
|
||||
"mirrored_text_on_front_layer": "warning",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"missing_tuning_profile": "warning",
|
||||
"net_conflict": "warning",
|
||||
"nonmirrored_text_on_back_layer": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
@ -113,9 +117,12 @@
|
||||
"too_many_vias": "error",
|
||||
"track_angle": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_not_centered_on_via": "ignore",
|
||||
"track_on_post_machined_layer": "error",
|
||||
"track_segment_length": "error",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"tuning_profile_track_geometries": "ignore",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
@ -123,7 +130,7 @@
|
||||
},
|
||||
"rules": {
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.16,
|
||||
"min_clearance": 0.15,
|
||||
"min_connection": 0.16,
|
||||
"min_copper_edge_clearance": 0.2,
|
||||
"min_groove_width": 0.0,
|
||||
@ -131,15 +138,15 @@
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.2,
|
||||
"min_microvia_drill": 0.1,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_resolved_spokes": 1,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.08,
|
||||
"min_through_hole_diameter": 0.3,
|
||||
"min_through_hole_diameter": 0.2,
|
||||
"min_track_width": 0.16,
|
||||
"min_via_annular_width": 0.15,
|
||||
"min_via_diameter": 0.25,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"solder_mask_to_copper_clearance": 0.005,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
@ -229,17 +236,28 @@
|
||||
"zones_allow_external_fillets": false
|
||||
},
|
||||
"ipc2581": {
|
||||
"bom_rev": "",
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
"mpn": "",
|
||||
"sch_revision": ""
|
||||
},
|
||||
"layer_pairs": [],
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"component_class_settings": {
|
||||
"assignments": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"sheet_component_classes": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
@ -429,11 +447,14 @@
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"field_name_whitespace": "warning",
|
||||
"footprint_filter": "ignore",
|
||||
"footprint_link_issues": "warning",
|
||||
"four_way_junction": "ignore",
|
||||
"global_label_dangling": "warning",
|
||||
"ground_pin_not_ground": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"isolated_pin_label": "warning",
|
||||
"label_dangling": "error",
|
||||
"label_multiple_wires": "warning",
|
||||
"lib_symbol_issues": "warning",
|
||||
@ -456,6 +477,7 @@
|
||||
"similar_power": "warning",
|
||||
"simulation_model_issue": "ignore",
|
||||
"single_global_label": "ignore",
|
||||
"stacked_pin_name": "warning",
|
||||
"unannotated": "error",
|
||||
"unconnected_wire_endpoint": "warning",
|
||||
"undefined_netclass": "error",
|
||||
@ -476,7 +498,7 @@
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.16,
|
||||
"clearance": 0.15,
|
||||
"diff_pair_gap": 0.16,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
@ -488,13 +510,14 @@
|
||||
"priority": 2147483647,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2,
|
||||
"tuning_profile": "",
|
||||
"via_diameter": 0.5,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 4
|
||||
"version": 5
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
@ -516,6 +539,10 @@
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"annotation": {
|
||||
"method": 0,
|
||||
"sort_order": 0
|
||||
},
|
||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
@ -587,6 +614,7 @@
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"bus_aliases": {},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
@ -594,6 +622,7 @@
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"hop_over_size_choice": 0,
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
@ -617,6 +646,7 @@
|
||||
"net_format_name": "",
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"reuse_designators": true,
|
||||
"space_save_all_events": true,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
@ -625,13 +655,28 @@
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
"subpart_id_separator": 0,
|
||||
"top_level_sheets": [
|
||||
{
|
||||
"filename": "usbc_soldering_iron.kicad_sch",
|
||||
"name": "usbc_soldering_iron",
|
||||
"uuid": "7095b018-eac3-4b01-b374-28e3216c4fd8"
|
||||
}
|
||||
],
|
||||
"used_designators": "",
|
||||
"variants": []
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"7095b018-eac3-4b01-b374-28e3216c4fd8",
|
||||
"Root"
|
||||
"usbc_soldering_iron"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
"text_variables": {},
|
||||
"tuning_profiles": {
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"tuning_profiles_impedance_geometric": []
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
18
sim/MMASU32MAB7106_PNA01.asy
Normal file
18
sim/MMASU32MAB7106_PNA01.asy
Normal file
@ -0,0 +1,18 @@
|
||||
Version 4
|
||||
SymbolType BLOCK
|
||||
LINE Normal 64 0 8 0
|
||||
LINE Normal -8 16 -8 -16
|
||||
LINE Normal 8 16 8 -16
|
||||
LINE Normal -8 0 -64 0
|
||||
WINDOW 3 0 33 Center 2
|
||||
WINDOW 38 0 -33 Center 2
|
||||
SYMATTR Value Temperature=25
|
||||
SYMATTR SpiceModel MMASU32MAB7106_PNA01
|
||||
SYMATTR Prefix X
|
||||
SYMATTR ModelFile MMASU32MAB7106_PNA01_LT.cir
|
||||
PIN -64 0 NONE 8
|
||||
PINATTR PinName Port1
|
||||
PINATTR SpiceOrder 1
|
||||
PIN 64 0 NONE 8
|
||||
PINATTR PinName Port2
|
||||
PINATTR SpiceOrder 2
|
||||
701
sim/MMASU32MAB7106_PNA01_LT.cir
Normal file
701
sim/MMASU32MAB7106_PNA01_LT.cir
Normal file
@ -0,0 +1,701 @@
|
||||
* LTspice Encrypted File
|
||||
*
|
||||
* This encrypted file has been supplied by a 3rd
|
||||
* party vendor that does not wish to publicize
|
||||
* the technology used to implement this library.
|
||||
*
|
||||
* Permission is granted to use this file for
|
||||
* simulations but not to reverse engineer its
|
||||
* contents.
|
||||
*
|
||||
* MMASU32MAB7106_PNA01 LTspice Model ( Temperature / DC Bias Model )
|
||||
*--------------------------------------------------------------------------------------------------------
|
||||
* Model Generated by TAIYO YUDEN Corporation (https://www.yuden.co.jp/en/)
|
||||
* Version 3.0
|
||||
* TAIYO YUDEN Control No. 250905
|
||||
* Copyright(c) 2021 TAIYO YUDEN CO.,LTD. All Rights Reserved.
|
||||
*--------------------------------------------------------------------------------------------------------
|
||||
* Product Description (link to TY-COMPAS)
|
||||
* https://ds.yuden.co.jp/TYCOMPAS/or/detail?pn=MMASU32MAB7106KPNA01&u=M
|
||||
*--------------------------------------------------------------------------------------------------------
|
||||
*
|
||||
* Begin:
|
||||
1E FD 14 DB 52 AE 58 6A 2E 81 BB EB 90 C3 0B 2A
|
||||
41 F4 3F AB F8 54 DD 0D 1E 08 9B 9B 3B 9B 47 A7
|
||||
EC B5 42 B7 92 B1 22 50 FC 89 DD 35 F1 E7 B8 26
|
||||
F0 C3 6C 8D A8 FB AC FD EA B2 BF 0A 8E 42 06 33
|
||||
EE F3 B3 AE 40 5F 78 0B 48 12 2D 03 C2 66 80 EE
|
||||
D0 C4 83 02 D6 2D C0 CD 42 D7 66 53 C4 6B 17 0E
|
||||
30 FF 6B 2E 99 B6 D5 BF 3E F8 CD 11 4C 08 95 08
|
||||
75 00 04 36 B3 0D E7 0D D2 01 DA E3 F9 C5 AE A6
|
||||
35 9E 29 2A AA C6 D2 7B 1D E5 F1 28 60 3B 6F 46
|
||||
40 EF 64 B4 BF 18 72 32 E2 01 BF F0 7A C5 9C 57
|
||||
2C A9 FD 41 74 D0 6F FF 04 51 05 E2 8D 82 6C 33
|
||||
78 00 EB AD BF 95 8E FB 21 36 58 B9 35 3B 96 BF
|
||||
ED 02 28 86 6A 48 BF FE AD 7B 35 A1 70 06 C5 3F
|
||||
A7 0A 91 D2 9F 0F 30 D3 37 30 95 7A C9 9F 3A 7F
|
||||
28 DA 99 AB 2C 9F B9 FA C7 93 DB 2B C4 DB 4A 68
|
||||
CC 1E 36 94 4E 85 03 8A 48 F9 EB C1 CC 7D CF B9
|
||||
76 73 49 23 2B EE E8 A1 92 DD 09 03 7C 02 45 4C
|
||||
FF F9 7C 8E 51 9A 06 FC BF 2F A3 9C 84 25 09 D4
|
||||
0A 0D 6F B6 82 05 2B 3E 6E 22 30 92 BC 83 2A 69
|
||||
13 6B 78 1F 44 13 C0 F4 5B 45 87 B6 92 FC 0C E2
|
||||
7B 0D 4B 2D E5 B0 57 CF 65 A5 78 92 52 3B 80 D3
|
||||
FD A3 F8 87 53 7A 7C 39 54 C4 EA 63 B1 8C 00 6C
|
||||
5B 17 87 98 56 93 18 62 86 1A 18 98 9F 28 B8 9D
|
||||
CB 9E B7 1E 81 74 D4 21 62 18 7F EF C5 3D 4F AB
|
||||
95 D5 91 E7 34 9A 17 11 B6 FD A2 D8 4A 9C 8B 2D
|
||||
3C 50 23 4C 2B 55 2D 7F 1C D9 99 F6 B0 13 80 A5
|
||||
81 F0 D7 45 0F 42 0B AA EB 31 97 22 8B 3A B0 E2
|
||||
E9 35 6A 14 02 CE FB EF 41 EF 30 A1 5F 7B E9 27
|
||||
B0 4C FE 8F D5 56 CE 66 51 0F A8 8A 4C 60 99 EB
|
||||
94 F8 B1 A1 66 4C DC 52 E2 72 F5 05 14 68 51 74
|
||||
EF 33 5A C1 0B E5 5A 7E 0F 33 00 E8 C2 69 3C CA
|
||||
FE 4F C2 27 15 15 81 9D 5E 2B 51 04 E7 7E 8B 55
|
||||
F5 DB 50 52 AC 74 DD 28 DB B4 33 EB 09 E4 35 C1
|
||||
76 84 36 84 A5 1B E2 B2 CB 64 16 6F E8 45 42 7C
|
||||
47 FA 21 7E EE 71 C1 68 58 BF 39 D4 8E F7 14 F3
|
||||
43 E4 34 86 E3 CB 7D 61 9D AD 08 26 2C DF 28 AE
|
||||
9D 49 32 33 13 03 00 AE C7 40 94 84 9F 70 15 4B
|
||||
31 14 29 ED BB E9 AF 95 45 0E EF 4F 3F 42 2A A4
|
||||
E0 43 AA 70 B8 40 90 3B F7 44 52 EF B6 DF C4 1E
|
||||
8A 4B F9 72 04 13 06 81 6D 04 FD BB EB FE 60 37
|
||||
A9 03 6D 93 36 9A 71 C4 B7 9F 43 59 EF DF 21 D2
|
||||
82 49 4E FC 72 79 27 36 EA 27 0F F1 9C 2A 7A 97
|
||||
D1 C5 B1 D4 AB DD 81 8B CE 1C E4 E1 54 AF 7E 9C
|
||||
BE 14 0C B0 79 48 AA 83 C6 54 D8 22 B0 A1 9C B7
|
||||
E8 31 16 80 C8 1C F0 B2 73 14 EE 36 6E 6F F3 46
|
||||
4C 2C 0D AB B7 7F 5C 70 6B D1 B9 0C E3 83 9D B0
|
||||
9E 79 D1 7A D2 39 B5 A1 60 48 0E EE F9 1E 4E EE
|
||||
88 55 53 F9 CE BF 60 60 CA 02 E6 6E 8A CF 73 30
|
||||
5F 1E 69 1F 3E 67 7C 18 5D 5F 38 C2 63 CB 98 3D
|
||||
AC 08 BE 7D B8 3B B4 6C 9B B6 DD DF 40 52 E4 A8
|
||||
0A 68 8A E0 09 E7 EF 81 05 52 05 DF 8C 0C 17 8B
|
||||
B0 A2 AD 59 42 6A 0F 72 27 CB 14 DA AD EB 94 E8
|
||||
10 2B BB 92 41 E8 5F 27 69 59 61 BE 30 B0 33 2C
|
||||
13 33 95 ED AE 73 6D 47 20 80 E3 C3 3A F3 FE 9E
|
||||
7F B8 FB BF 93 60 A0 9E 47 CD 1E DE 68 93 F0 C4
|
||||
CD EA E9 88 B0 52 57 79 37 DF 02 93 8A D3 A5 76
|
||||
03 DB BB 13 81 D7 DF 57 C8 A3 D5 D7 F4 64 8D DC
|
||||
2D 65 00 87 78 BE 95 B3 C3 5D 20 58 E7 F8 91 2D
|
||||
A1 3D 03 30 28 F0 81 54 2E DD F0 FE AC A6 88 A4
|
||||
0A DA BE 9F B4 71 A2 9C 94 7C AA C2 A4 4E 66 9C
|
||||
1F 58 8A 43 CF 2B 3B 16 DD 0F D7 93 11 E4 0E 28
|
||||
31 2F 6F 1A 96 C2 08 B0 E5 93 16 11 A2 E4 97 55
|
||||
D5 F2 D4 9C F4 6E 78 77 98 46 09 03 76 2C 49 2D
|
||||
77 CE 17 D6 17 27 18 4A 53 FA 4E C7 BA 56 42 93
|
||||
01 CD A5 B0 7F B7 6C 60 0E FE 84 86 DD 0B F0 D0
|
||||
10 A6 DF 53 7A 78 31 B4 99 1B 2B E4 FB 36 41 9D
|
||||
04 C0 12 41 F1 81 E6 B0 33 0B 2D 70 0F 04 17 37
|
||||
78 79 23 52 DF AB 20 91 D6 2D D1 6C FC 1F 48 CA
|
||||
E9 23 6C 22 76 9E 0F 78 2C D6 FE 31 58 DC 3E 3D
|
||||
78 0B 92 91 2E F0 06 CA A4 2D B5 C5 95 46 AB 18
|
||||
B1 6B BC 7E DB 70 49 39 6F 0A 0A 3C A5 E2 28 B8
|
||||
8A A2 8D D8 E5 F5 35 CB D3 97 65 3D 4E FC E0 41
|
||||
44 E3 88 BC 72 F6 A6 76 69 F3 67 DF B1 EC CF 7D
|
||||
AC E6 2C D4 41 51 B9 CB 15 B5 BB B5 04 81 35 3D
|
||||
30 7E 61 30 29 1E 4D 41 91 56 B8 35 8F D5 04 2E
|
||||
1D 18 6B C7 5A 6B D6 C9 28 FF 7D 8B EF 3C 17 98
|
||||
8D 26 35 DB 1C 9F 7E D6 76 A7 B0 6A 27 B1 1A 07
|
||||
48 9E 99 56 47 4B 91 32 B5 DB 75 27 65 99 26 B6
|
||||
F6 BD 98 7E 41 1D 88 B6 D7 DC 1D D0 0C F6 4E A8
|
||||
8C 50 84 5B 5D 21 26 0D CB A1 E8 25 82 ED 91 BE
|
||||
8C E2 96 BD B1 25 11 0C 4A 04 8A 6D 3C F6 FE CD
|
||||
B7 BA 45 6B 66 46 80 57 E8 1F 0A 95 67 3C 67 E3
|
||||
4E 49 13 40 07 5C CD F0 A3 5F EF FB 07 38 75 0C
|
||||
D3 A2 FA 31 C7 15 DE 56 96 55 3B 67 1E 89 75 BF
|
||||
C6 AB D4 51 2B 96 85 70 9C 22 25 62 11 D2 1E FF
|
||||
C9 04 5A DC 97 47 42 7B 8A 9A 85 FE EC C5 1A 7D
|
||||
85 AA 05 6C 51 47 AE 61 91 AB 9E 5A CE DB 69 FC
|
||||
45 35 8B BD 89 EC 5B 62 6D D9 A0 AB 5B 96 FC 40
|
||||
43 6E 46 8A 7A 94 92 14 4A A5 E6 E9 26 6B B6 58
|
||||
17 59 A4 3B 8F C0 E9 9A 4A C7 DF 57 57 33 90 52
|
||||
B4 9E 9E 0D 91 B8 91 DB EA 89 68 78 A5 CC 61 F9
|
||||
A9 EB 10 94 B0 0F 5B 08 A9 46 BE 55 62 10 2E E2
|
||||
76 85 CD 09 92 40 42 C0 33 4B 28 48 4F 25 0A C3
|
||||
B2 3D 53 0B 32 DB 1E AD 79 74 A9 E4 32 9B DD 51
|
||||
0B 9B 7D FA CC B4 02 C8 1D E7 9F 2C 1C E4 B0 F2
|
||||
54 28 72 23 F1 74 D6 59 12 6C 1F F8 47 3D 24 4F
|
||||
8C 05 95 F7 CE EB B1 0F 15 76 74 07 93 6C 24 3A
|
||||
E0 F8 D4 B6 99 D3 B1 89 13 07 26 63 74 9F 17 B4
|
||||
E7 5D 46 69 3F F5 45 07 F8 1F 53 87 1A A0 0C A3
|
||||
10 07 5C 39 5B C0 5D C8 C6 17 C7 48 3E DC 2B 0C
|
||||
DA 67 7B 56 34 F4 7E 00 92 34 10 2C 5A 83 FB C0
|
||||
71 F0 91 16 BA D6 BD 9A 8A 70 63 30 30 28 D6 EC
|
||||
EB E7 56 92 A1 2A 08 20 B2 02 A0 44 05 AA 7D 70
|
||||
7E DE 8E 49 0D 08 10 87 77 5F C3 7A DD 94 4C D4
|
||||
13 4D 3E F3 B3 48 CC D0 C9 4C 97 C9 B1 AD 23 B7
|
||||
B0 92 4C 1F 1F BB C7 CF 1C D5 34 39 25 C8 AC EF
|
||||
D6 F4 24 7F 3A C9 74 B1 65 5C EC F5 5C 4F 9A 6B
|
||||
18 98 11 6F 1C 9D 3F D0 0B 2A 0E 84 74 96 3C 47
|
||||
B6 EF D4 8E D3 27 1F 7E 9F 2D DC 95 9F A9 0D 17
|
||||
EA E0 0F 99 82 02 E6 66 37 03 69 6B 91 30 41 FB
|
||||
C6 1B 06 51 39 8B DE EF 36 56 58 9A 5C 00 0D 08
|
||||
60 1D 7E 7B 38 67 4A B5 4D 0D 98 FE F8 A1 BD 04
|
||||
E5 4B 92 F8 C6 1E 69 4B 91 7A F2 75 8E 0C AB 7A
|
||||
30 63 92 B2 B2 2C 72 A2 E5 05 FB B4 4F 81 1C 2F
|
||||
EA AC D2 2F C6 D9 31 3E BD D2 3E D7 BE 83 31 F6
|
||||
C0 97 FE 72 D9 8C 6C BC 51 27 06 CA 7A 1E F4 55
|
||||
34 5F E3 5E BF C8 85 B9 CB E3 0D F9 96 DF C9 76
|
||||
39 81 26 3A BE 47 80 AD D0 B4 45 75 D8 EC 13 63
|
||||
1A 28 85 42 F0 66 0A E3 AE 7A 78 F2 5F F4 F3 B4
|
||||
75 12 49 F7 DB 2B E5 5D 76 14 CE E0 4F 5B C8 EC
|
||||
63 BD 05 C9 4E 80 79 10 D9 97 AA 85 4A 4E DB 36
|
||||
F2 B2 24 E9 24 88 8E 64 EF 3D 31 AE AB CE 1B F6
|
||||
5B 6E 5D 0D CE 96 D2 6E 92 6B F8 7C 28 4B E8 75
|
||||
1E 6C B1 18 BB 13 86 53 17 14 C1 82 AB A0 40 A2
|
||||
45 C5 5F B3 35 55 DD 4A 19 27 80 8E 5C C7 FF A4
|
||||
AB E1 0A F9 91 87 73 38 D4 4F 18 AB 80 8E 4E A3
|
||||
67 5E B1 FA 5B FB 84 C8 59 24 0F 4E 2E DD DE 9A
|
||||
B9 30 1B B5 44 56 9E EA 84 BA 82 CE AF 9B 31 D4
|
||||
D0 5B 0B AB 91 3F 59 D5 01 3A AA 32 02 80 D1 AA
|
||||
E9 04 E4 4E 81 26 8F 5C 9E 89 5D 5F 7C 48 9F A5
|
||||
E1 A9 FE A6 4D EB 9A CE DE 73 26 F7 2F 66 83 7E
|
||||
CC CD CF 35 95 FA 21 32 9D E5 BB D1 13 BB BD A1
|
||||
4D 2E 98 18 B5 71 50 72 7D 81 93 22 45 06 D1 00
|
||||
0A B8 84 03 06 3D FD 81 B1 22 01 D8 83 A2 06 D4
|
||||
BA 29 55 C0 92 E5 92 36 94 AC 9C EA 6E 87 6D A8
|
||||
D4 33 9D 8F A7 55 08 62 B3 0E EB 78 12 E8 89 37
|
||||
62 1A 77 F4 07 62 C7 47 AB 05 28 36 2E C1 AF E2
|
||||
8D 22 F4 13 44 3D 8A 41 1C 3E 9B B6 41 1F BC 5D
|
||||
3C 22 C5 EC 9D C2 C3 5D D7 E9 FF AB 8C E5 CB C8
|
||||
1B 8A E8 75 33 5A DD C7 A6 7E 3F 78 B9 CB 63 C9
|
||||
69 3D D8 FF 6F 72 37 D8 00 96 9D 2C 8E 4B 72 57
|
||||
E6 BE 3C 04 A2 2E 65 10 77 B4 87 F5 E1 E5 F3 F2
|
||||
D0 22 8F 51 11 44 BF 4D 40 53 BA 7B 04 43 94 93
|
||||
7E 17 FB 43 0E 09 E6 18 98 DB FA 2F ED 18 9C FF
|
||||
6F 62 12 07 21 D3 CB 98 D7 C2 AA C3 A1 6F A7 30
|
||||
12 47 EC A1 94 A7 06 36 4A 86 4D 5D 2F 14 A8 2E
|
||||
FF 2B 8A DA C3 33 C2 4F 14 E0 C1 04 F0 DC 7A 1A
|
||||
58 1C C1 B3 0B 2D E3 1F E2 54 01 BD D2 D0 A7 3C
|
||||
0C F8 EA D2 B4 0D 43 F0 7C 2C EF E7 94 43 4E E2
|
||||
FA FB 90 2E FA 76 CA 51 1D E2 F5 C9 85 05 30 59
|
||||
5F EE D0 6C C9 3D D7 40 9A D9 76 6E 3D 6C B5 81
|
||||
E4 67 79 0F B5 8F 80 C0 2A 95 AA A6 6D B3 BD D5
|
||||
73 21 98 1D 86 5F AF 8D 98 9D 74 22 99 03 7B 58
|
||||
7C 23 63 41 7B DB D2 37 DB F1 B9 C0 44 7E 6A 4B
|
||||
2A CD 2C DD 99 D4 E2 4A EF 7C 12 51 86 7D B6 E7
|
||||
23 31 69 11 D4 32 C6 0A 24 DA DB 81 1F 8B 10 3E
|
||||
FE F5 D1 3C 16 9E 11 B4 14 37 50 1E 30 D5 B4 EE
|
||||
F2 EC 34 08 F7 20 FF CC 11 D2 DF 37 03 F0 C4 F2
|
||||
C3 CB A3 60 B7 71 26 36 7A DE 69 97 63 AD B2 ED
|
||||
E5 9D C2 45 19 31 0E 35 C7 96 D9 65 60 C9 92 99
|
||||
B7 29 28 28 1A D9 F8 BB 0B 09 B1 E5 2C DD 39 58
|
||||
B1 AE A8 0C F3 A3 2A 88 FC E2 C2 B5 A2 73 A9 78
|
||||
3A EC AE D5 6F EC C0 62 33 24 2C 1C F1 27 BD 97
|
||||
4B 93 9D 21 19 46 4B 0F 92 2F E3 61 93 91 19 91
|
||||
1D 31 24 19 D5 2C 1D A8 D3 B8 01 0E 36 E9 1A E5
|
||||
07 3E EC 55 21 5E 7D 41 6E 2B C5 C5 B8 8C 9F E0
|
||||
FA C7 97 48 89 02 86 5B F9 17 E1 A5 53 4E 62 5B
|
||||
B0 C6 D8 AE 15 45 E8 DC 1F 98 0C 18 EB B7 16 22
|
||||
FA 86 FE DC 35 B4 AF C4 ED D0 7B C2 17 68 AC E1
|
||||
32 D8 9A A2 EF 37 B3 1B E7 0C 35 5A 18 A2 82 CB
|
||||
57 2D 98 76 FB BC AC B7 1B 3D 16 54 A5 14 11 C0
|
||||
E6 C1 A4 71 F2 7D 92 52 20 67 D8 03 F3 78 D5 F0
|
||||
B2 E9 22 63 AF 92 C0 1C 1C 42 38 F9 78 FC 31 F1
|
||||
6A 5B 79 05 7D 7F FA 59 59 63 65 D7 8B 50 E1 46
|
||||
B0 EA 93 6B 2B F3 7C 39 2F C4 00 D7 CE 53 6C 50
|
||||
DB DF E1 73 AC 6E 22 3B 92 D0 5E 5E 9A C0 9E 29
|
||||
3A 2D F4 FF B8 12 88 36 C0 0F 44 39 80 0E FF 6D
|
||||
47 BD 0B 78 FD 03 57 F6 F0 22 B4 2E D1 8A 2D 6E
|
||||
A6 DE F2 DB 99 C2 BB 98 D3 73 87 3D 60 F5 F9 70
|
||||
D8 49 86 F4 77 9C 18 59 D0 68 CA F7 26 AC 78 90
|
||||
51 25 DB 18 A1 CC 67 45 18 23 A3 AA 26 21 B9 F7
|
||||
C9 08 E0 6D 16 E8 4C EC 57 74 F0 63 C4 5F F8 1E
|
||||
1F 05 83 E6 9E A7 9D 43 41 E4 72 10 45 0E E0 09
|
||||
63 C2 85 E5 04 7C 07 82 90 D1 B3 95 B6 50 19 2C
|
||||
76 9B 1F 99 93 7D 61 76 1C E6 E7 B2 A2 2F E0 F6
|
||||
35 27 82 13 AC 02 C2 D8 20 CA 9E EF FE 32 CB 21
|
||||
B2 D8 01 A5 52 65 79 A1 EB E0 5B 75 7F FA CC 5E
|
||||
53 D5 63 CA B8 BD AF 0D C3 A0 C4 A8 F8 0F 0D 86
|
||||
15 EA 8A 42 BB 12 22 8F 72 DB 4F 4A B5 AA 44 3D
|
||||
76 8B F4 B8 5B E2 42 CC 74 D9 1F 8F A5 F6 6D 2E
|
||||
2C 30 C1 3C 1B 87 D8 6D BF B4 82 6D D6 04 C1 DC
|
||||
7C 45 2F 3C EA 8C 61 A2 AA CB F7 DF 11 76 BA 79
|
||||
E0 B3 7F FC C1 B5 81 85 86 2F B5 2D BB 94 E3 40
|
||||
BC 16 FE 56 A6 5B C1 CF 63 37 96 1D 2A A2 0C FD
|
||||
A0 DA 29 E5 C9 93 83 D2 C7 A1 FB 12 39 B7 A4 FE
|
||||
17 05 B5 74 78 EE E9 D4 7B EF 58 81 5D 85 42 C7
|
||||
86 F4 FC 57 1B 3F A5 7A E1 A0 C1 D1 2B 38 C4 74
|
||||
F2 AA 43 40 2C 28 E1 35 64 15 E0 11 0B 30 3B AB
|
||||
3C 0F 79 20 39 D6 93 F4 91 6D 77 E8 D9 9E 2B 58
|
||||
89 43 62 58 89 59 99 D4 D3 B2 AB A7 E0 74 26 DF
|
||||
68 5B 1B 38 BF B0 87 04 0E 4B 9E B1 83 B7 42 89
|
||||
A4 04 AB 39 32 32 38 57 1B 31 C1 CA 5F A8 CE EA
|
||||
36 27 FA 2F EA D8 4E 20 66 68 70 5C 65 32 1D 15
|
||||
B6 EA 66 87 9A D9 49 73 09 06 AD 7E E5 B5 CA C4
|
||||
8B ED 4F 65 69 6F 19 75 34 84 3D 8D B3 99 A8 67
|
||||
EE 09 7B 59 F2 12 D3 F4 8D 22 41 2B 9E A7 CA 43
|
||||
C7 71 5A 1B 3E 93 92 01 B2 1E BB 1B DA E8 F2 41
|
||||
49 24 51 C4 04 CE CC CF 47 BB 2A A9 23 A4 57 32
|
||||
C9 72 3E CB 4D 9D 9F BB C3 BF 5D A7 46 0A 8A C1
|
||||
54 D9 42 69 5F 26 7C 79 F0 F4 BF 70 7B 4F 67 99
|
||||
90 73 ED 59 82 55 DE 70 F1 8A 97 FB C9 96 86 CC
|
||||
6F BD D0 A1 C0 44 4B 63 DF 65 B0 7E CF AC 2A DD
|
||||
C1 2B 1B 14 7F 6F 06 8F 12 34 43 24 59 DC 08 34
|
||||
02 A5 22 83 7E AF C1 B1 E2 1E ED C8 49 E9 95 CB
|
||||
F7 F4 A5 30 5A C9 E7 4B 9E 29 EA B0 8C 7A 1B EE
|
||||
E2 67 86 71 0C 5C 35 14 CC CC F9 E7 96 FA 6C DE
|
||||
19 D9 85 A4 B1 1D 9A BE 25 10 16 01 BC 8D C5 A9
|
||||
B2 54 66 48 67 06 F9 27 9A 90 D1 63 3F 61 AF 1C
|
||||
C1 62 F7 04 2E F4 08 BC 18 63 53 F5 B5 E5 D5 0B
|
||||
15 0D 3B 15 C3 6A 23 D9 3A AA 5D D0 63 9D 93 59
|
||||
C2 03 55 C7 27 92 E1 A1 90 0C F6 00 87 12 E2 A5
|
||||
70 B8 8C FD D3 8F 53 61 EA 91 06 DD 61 36 3C EA
|
||||
14 E9 FC F6 C6 82 24 24 71 DA 21 50 9C 25 67 BC
|
||||
DD 98 6B 65 57 C1 AB B8 A7 F9 A6 16 C5 55 33 C0
|
||||
75 5E DA 18 A6 67 C9 C1 E6 3F 65 18 55 FE 54 9C
|
||||
16 CD B8 84 18 2D 6D 28 1A D6 2D 64 5E 03 40 D6
|
||||
31 3E 6C 29 EB 42 0B D1 56 41 3D 70 D0 C5 93 E1
|
||||
3B 77 9A 08 E0 28 B2 9B 20 14 A6 2F 07 45 DB C8
|
||||
EA EB 0D 9B 7E AF 79 5D 1B 88 EF 5F C6 B6 E6 76
|
||||
84 1B 23 34 39 97 50 73 96 A1 D4 E4 13 DB 8D 3C
|
||||
6E 48 DB 56 69 7B 03 3A 0A D7 27 5E 90 8A FC FC
|
||||
09 56 93 E8 32 E6 84 64 A9 E9 1C F0 CF B1 91 E0
|
||||
AF 4B AD 6C C6 F8 F2 4E 86 66 DC D8 4B F8 44 A3
|
||||
06 02 3D 60 A3 95 F5 55 DE 33 D3 4C 35 81 78 2E
|
||||
5A B4 93 F6 4C 87 E5 34 1D 85 2F EB 4B E7 42 56
|
||||
4F 71 B7 DC D5 EF AD 96 DF E9 46 62 97 5B 09 72
|
||||
3B 10 C5 95 4A 32 BA 23 91 48 A4 80 AC 9F 45 61
|
||||
7D 98 A7 D3 7A 9E 9E 1E 28 D3 99 0A AD 07 E2 89
|
||||
0B 01 56 66 BB 8D DE 04 DD BB CE 4B 8C 33 36 F3
|
||||
69 78 CD AA 64 D5 04 A7 33 EA 9F 82 73 02 0D 82
|
||||
09 3F 46 F6 24 C4 FA 5E 1F 15 2A 7F A2 98 7D CF
|
||||
A0 39 06 85 88 9D D3 94 92 77 06 13 8A E5 15 6D
|
||||
EE 60 40 76 C7 4F 0F 1F 2B D3 AD A4 1E EC 26 2A
|
||||
D4 2D EA 4B C4 3F 19 EF 59 21 BB 9F CE 70 D2 9C
|
||||
21 C1 69 E3 9B E9 9C 61 A2 B1 7B 95 E9 1D 6B 3E
|
||||
7D 54 9A 29 A0 F5 D5 6C ED 33 69 DB 3D 20 DB 5D
|
||||
2A 76 91 0D CB E9 11 F9 53 8B 4A D9 70 25 F5 13
|
||||
F8 41 1E B3 01 77 8F A2 9B 9C 00 AE F2 BC CC B3
|
||||
AA C8 FB A9 17 92 49 EC F3 91 5B 68 8F 98 CE C2
|
||||
A9 60 D9 67 CF 1F 07 C8 6C A9 D0 6C 2C 02 F4 1D
|
||||
9F 05 1D 88 5B 3B F8 93 2B E5 9A 41 25 85 02 73
|
||||
F3 E1 D4 EA 24 2E 41 FA 69 5D 18 C8 73 DE 17 D0
|
||||
00 E6 C7 03 CF 0F FE 4B 48 B5 E6 46 EA AB 26 58
|
||||
92 9A 3C E2 66 2D B6 19 CB 02 5B FC 67 CA 2B A4
|
||||
EA DB 15 35 43 55 EF E9 B1 97 D2 86 0A 9D 57 23
|
||||
98 2F 31 B9 95 BF DB 76 07 73 32 88 72 7C 24 EA
|
||||
29 C3 D0 A5 81 F8 9A B4 88 61 23 BF A0 E2 12 D1
|
||||
B4 94 0D F3 70 BF C7 D0 02 90 E4 8B CD F0 31 15
|
||||
5C 10 16 5F 33 50 44 7E 2D 5B B6 99 1E 07 43 0E
|
||||
93 31 EB CF 9F 3F 6A 10 E1 64 CB 2D E4 08 8D 2C
|
||||
E8 BD 4C ED 23 EB 74 D1 87 13 FB 09 39 57 62 F7
|
||||
61 A3 6F EC 2D B4 EF 80 35 00 6D 7B 7B 33 20 ED
|
||||
48 9D E4 4C A8 E2 5D 2C 02 41 02 F7 6C 1C 37 AB
|
||||
45 AF 5B 78 8F 05 C1 30 E8 16 6F 5A 61 22 4E 02
|
||||
37 0C 9A CD C9 79 B3 B7 47 BF 4F 22 9C 8C 23 65
|
||||
5D 8B 59 91 A0 67 7A 4B B3 03 9D B5 45 72 BA 34
|
||||
61 73 5D 6E C9 32 83 1E 8F 48 D3 F3 E3 F3 DA C9
|
||||
4B 1D AC 88 AF 7C 08 77 77 6B 87 7D AC 54 DE BB
|
||||
74 31 5A 32 88 BB 11 74 42 5E 6B AE AD E5 76 7C
|
||||
0D 0F B0 DF 47 F4 BE E1 20 E3 99 8A 1F 7A 90 27
|
||||
C1 9F 2F 03 5B 7C 16 96 89 C1 4B F2 74 35 13 3A
|
||||
05 7D 65 7C BC ED 05 4C D8 E7 5D 7F FE 6C 43 A8
|
||||
86 7A E4 25 9C 66 73 87 37 0D 97 22 E3 4B 66 36
|
||||
41 EE 49 2C E3 71 46 6C 97 17 EC 57 B4 D9 42 56
|
||||
BA D8 57 D8 96 B3 7B 31 DA BA EE 24 56 F5 B9 F0
|
||||
15 5E 6B B0 9F 79 AB AD 81 6A 08 C9 68 8A E9 7F
|
||||
86 59 DD 09 31 CD B8 69 B1 25 04 74 C6 7E 69 9C
|
||||
6B 1E AB B4 B9 18 95 C0 BC 1F 9A B6 48 5D B2 4C
|
||||
1F AA 5A 3A 74 38 B4 8F B6 D1 BD 02 E8 0A 3A 5C
|
||||
0D 0A 5C F9 5D BB 42 83 4A EC 70 3C 4E 36 D8 B1
|
||||
40 62 91 79 C7 04 F7 05 BE F2 32 E4 EF 06 DD 25
|
||||
40 B1 56 2C E8 90 25 6D 62 29 11 E2 33 31 4D C9
|
||||
D8 5A 95 44 D6 E7 B2 D5 F5 61 66 6F 1A 40 DC 4B
|
||||
45 50 E2 73 01 65 CD BD 5A B6 E5 77 13 05 D2 17
|
||||
FC 6C 72 5B 8E 46 DA 58 DC E1 DE B0 08 7C AE 67
|
||||
5D 29 A6 E2 B3 99 B3 30 29 F5 F3 ED B2 46 F4 CA
|
||||
94 E0 B9 94 14 C6 00 B9 61 44 93 E1 29 B1 6A C1
|
||||
38 FE 49 5F 9D 45 32 4F 73 40 4C 09 08 C9 D8 D9
|
||||
C4 65 08 D0 2F C5 48 7A 6B 50 1C AD 88 EF 76 7B
|
||||
CD 96 C3 6E 71 C3 13 6C 3E 9E A5 8E FA 86 C2 42
|
||||
42 24 B7 0D FF 0C 1C 85 87 B3 9A 4E 9F 9F C3 86
|
||||
04 B2 CF DD C0 0F 13 E1 6B A8 EE 00 0A 18 3B CC
|
||||
3E 40 63 4E C4 5B 44 F9 56 4B FA BE 0A 62 DC BB
|
||||
17 49 84 36 B1 D9 E6 38 3B 06 78 E1 34 8D 32 42
|
||||
05 65 13 18 9F 33 9B 5C 67 96 17 3C D8 79 FB 01
|
||||
7B 49 02 FB 78 8A D1 3E FD D2 0B 24 96 D0 D0 9A
|
||||
BE 91 8A 8F D4 B1 F1 C3 D2 7C 75 E7 34 78 59 F5
|
||||
BE 41 6A E7 9E 03 22 30 67 41 DD D8 84 6D F9 47
|
||||
5F 04 B0 EE F2 A1 CC 69 9D 11 54 E2 01 D3 67 93
|
||||
98 FB 25 52 47 AF 4F AF 9A 6F 29 85 47 64 87 DA
|
||||
61 AE 1E B1 64 EA AC A6 D3 CE 62 99 96 73 DF FA
|
||||
AA FC 0E 7F FA 05 50 84 BC F4 57 DC 0F 01 36 10
|
||||
33 84 50 C6 4B 54 38 C8 20 28 9B 75 4E 93 B7 2E
|
||||
FE 8A 14 AC C5 DE E6 36 F6 4A 13 06 E8 EF D2 3D
|
||||
63 46 9E 5F 46 3A 51 0E 6B 53 08 FC C3 7F E6 90
|
||||
4C 81 03 BC A8 81 EC 88 79 F2 82 F3 C9 22 84 4A
|
||||
0B 43 94 BA BF 3D EB 75 50 F0 3A 08 C9 A9 2E 04
|
||||
C4 0E 1C 3A 07 70 DF E6 64 CC 51 ED D0 FB 5E 37
|
||||
6D EC 10 88 D7 F1 8F 0C 1D A5 2E 22 BB 86 29 5E
|
||||
E7 C1 A0 CC E0 48 A6 1C 54 46 A9 26 48 72 C0 0C
|
||||
2C 7C B1 73 6F 12 3F E1 6F 58 58 C6 DC CD B1 19
|
||||
EA 82 B2 3A 26 8B C9 87 7F 1C 33 6D 78 0D 11 19
|
||||
3D AA 14 9D 2A 0C 27 E7 5C DF 66 90 A9 3C 9F 47
|
||||
15 60 4E CF 51 ED F8 2F AD B1 3E FE 33 73 13 E2
|
||||
4F D5 AA DF 11 75 C2 D7 68 0D 08 4F 0A 4D C8 B1
|
||||
B6 B6 6E F7 D3 92 4E 5A 38 7A 73 8A 5B 10 C0 22
|
||||
07 F2 27 63 1D 41 02 BD 94 37 4F 94 50 F8 EB 93
|
||||
43 47 44 11 B2 33 8D DE 52 8B 85 C8 7D 68 96 CF
|
||||
7C 6B F7 0E A4 9D 2D F8 1B 9A 85 CD AE 83 9B 40
|
||||
A9 EF 66 A5 CB F8 EF BF 2F 3E 60 06 05 4C A3 FD
|
||||
22 47 FD CF EE A4 8E 55 4A 69 E4 64 50 58 A1 15
|
||||
8B 88 BD CA 0E F1 ED B0 C2 AC F0 34 87 BD 00 B1
|
||||
EA 94 14 4C 7B 1A 2E 80 F2 05 52 97 70 66 5D 3B
|
||||
BA 7E D0 BB 95 2D 01 8C 4B 7D D6 7F 85 AC 98 B9
|
||||
50 EA AF 0A 3D 4D C9 7E 85 04 6D BD 00 C0 1A 9C
|
||||
01 6A D4 A3 27 8A 3E A3 AF 27 23 25 E8 15 19 5D
|
||||
45 1C 9F 84 16 6D E0 26 5B 83 AB 11 D9 F4 79 E1
|
||||
09 B2 06 D5 B0 83 88 E2 8A 30 B4 5E A3 F4 BF 0E
|
||||
54 4E 22 77 36 28 95 0A F3 B7 86 2D A7 BC 29 EE
|
||||
FD D4 03 1F EB B5 21 E0 95 6C BF 14 A0 43 CC 70
|
||||
C4 85 0F 88 23 44 66 AB 05 DB C6 27 41 B1 18 33
|
||||
5A CB EF 89 2D 68 70 DC E4 F3 8F 52 E7 75 B1 63
|
||||
34 6E FE 4B A4 D2 B6 C4 9E 0A 7C 46 58 77 CE 5F
|
||||
5C BF 10 F7 3E B8 EC DB 4D F6 DE 12 4F 40 7E A0
|
||||
24 61 01 50 E4 41 C4 DC 79 28 0C 05 29 2C 47 0F
|
||||
15 09 FD 23 22 2C 28 E0 7E 26 48 D9 44 CE 10 FA
|
||||
35 92 B3 32 C9 00 F8 0A A6 64 F6 66 96 8D C1 75
|
||||
9C 1A AA 91 56 85 62 BE 00 25 97 58 0A 0E B0 11
|
||||
C9 D5 33 37 A8 1C 0A EF 59 A7 D7 10 EB A8 87 20
|
||||
9A 86 C0 B0 1C F6 61 AF F5 F3 2A 69 3B 89 CE 26
|
||||
6B BF 09 D5 ED 65 35 A3 83 47 0C 61 CB 57 9D 51
|
||||
15 D8 0F 2D 7E 1E 7A 9D 31 4A CB FE D0 1D 8B 72
|
||||
6E 67 1C A9 76 05 84 67 91 3A 33 0A CF 96 59 1B
|
||||
6A DD D9 8A C4 A3 AF AC 7C 82 25 7F D3 A7 3E C4
|
||||
92 0B E2 9A EB B4 77 C3 DC 5D C3 D6 F0 17 33 60
|
||||
B8 C1 57 3B F9 7F 3E EC 2B A2 3F B5 29 56 BA A7
|
||||
B5 B3 42 57 84 0E 9B 6B A0 01 EF A0 D2 59 98 A3
|
||||
E0 7A 6D BD 9C 80 1F 50 D6 58 55 E1 34 21 22 94
|
||||
70 05 A7 DF 9F 68 88 55 7F A3 2E 86 BE 23 A3 5A
|
||||
EF B0 D1 F0 68 88 01 81 07 82 D6 B8 45 40 D8 23
|
||||
59 A8 BA 1A C4 6E 78 43 E0 28 14 A2 52 60 C6 A7
|
||||
64 6A 5B F5 1F C8 EF 65 EE 40 2C 2A 4E D1 AF AD
|
||||
39 63 32 21 F0 AF 96 74 56 13 A6 6E E3 AE 9F 86
|
||||
A7 F7 3A 68 D9 CD 21 65 E7 F5 E2 E3 F0 6E 1F 27
|
||||
D4 E0 E6 BF C1 37 AC E9 3B 54 42 1D 41 12 1B 55
|
||||
6D DE F6 C5 39 52 21 F6 40 67 03 F3 FA 92 E5 6E
|
||||
4A C6 00 BA D6 71 82 B9 F1 B8 A5 61 61 2E B5 C7
|
||||
C8 8B 78 9F D1 4C BA 66 AC C6 35 5B 07 9B 68 84
|
||||
4C C9 8B 70 7B 81 EA 83 18 CD 78 3E 76 FF E7 D6
|
||||
2E B9 6C 79 AE 30 01 6B BD 05 7C 97 ED 67 94 C8
|
||||
3B 93 A8 58 35 32 7E 88 92 D4 D8 17 0B 24 C5 56
|
||||
82 7A F2 F5 E9 09 C0 44 83 9B 8D 6A 42 56 D5 12
|
||||
BB EE 3D D8 ED 66 A3 49 0E 4C 61 47 A4 3F DD 15
|
||||
78 B8 C0 1D 9E B8 06 40 CA 1B B0 8D 27 71 0B 6E
|
||||
50 25 EA 53 1A 2E 99 41 26 6D 78 91 7C DD EF BB
|
||||
59 D3 48 62 2B 9D A8 2A 5D FC 60 EF 87 72 B8 FC
|
||||
7C E4 F1 81 BA D3 F0 F3 37 2E 5B 58 5E DD 0F 84
|
||||
EE DD 76 54 95 12 EB 2C DF 5F E7 F0 07 76 46 E3
|
||||
D9 96 EB 30 04 C3 57 20 B3 0E F8 B0 0C 39 5C 9D
|
||||
AD 4E D9 CC 2C 2C 31 BD 6A E4 92 DA 55 69 F5 43
|
||||
7F 96 FC 23 89 40 F5 D8 07 13 72 6B 03 38 CC 45
|
||||
D3 9B D4 61 32 79 25 91 76 AE 93 31 9D 3D BC 9A
|
||||
07 53 EB 34 A4 39 AC 3F 5E 49 15 CC 19 A5 2A DA
|
||||
F7 2E 3B 06 79 B7 B3 87 E7 5A 2A 55 7F 8D 4C A2
|
||||
0D FB 88 AA FB 9D 34 1E 8B 6F 4C 6F 25 1B F8 24
|
||||
FC 81 56 B6 70 99 41 4C FF 13 EB D9 C5 7F C6 70
|
||||
97 B9 2F CC F4 42 86 0C 3A 21 56 C3 4C 21 3C F9
|
||||
A5 3A 50 96 BD E6 7D 6D B1 5B FD E7 0C A5 EC A3
|
||||
31 53 DB EE 41 25 F8 F8 B6 02 D7 5C FE 49 03 95
|
||||
D5 EE 7D 85 46 1D 6F 85 5A A9 1A 33 F5 EA 83 D7
|
||||
BE 48 65 22 F4 0C E2 AE 4B 97 33 03 C0 13 2A 23
|
||||
C8 2B A2 C0 CD 69 7F AD 50 45 8A 3A 2F 44 38 C8
|
||||
C1 A4 DF 61 7A 75 BE F6 84 37 B1 26 4F C1 E0 30
|
||||
EB AD DE 9E 75 B8 2D 71 AA D7 40 D7 64 3A 12 C3
|
||||
DD E7 30 1F 3B 9B 86 AE F0 DB FD EC 61 64 B6 4E
|
||||
6D 53 76 D7 0B 32 F4 2A 00 E7 E2 5E 4E 9A 2C 84
|
||||
4F 48 A5 FB 94 FE B0 59 0B E2 77 3D 71 22 EA F9
|
||||
5A 73 1B 38 98 80 2A 41 6D 8F 62 E8 13 90 39 EB
|
||||
38 73 19 D5 EB CE ED 56 2D A9 E6 A2 6A 62 4D 49
|
||||
A2 BF 29 E0 B9 A6 35 86 F3 D8 71 B5 96 EC 53 CC
|
||||
53 90 2E D6 4F 2F 4D 51 97 A2 C2 5D C7 EC 88 E8
|
||||
C2 6A 5F 01 8D 56 0C 4E 5E 8C 96 FC 9E EE D1 FF
|
||||
89 DD 1E 72 D4 AE AA 7C C6 77 DF 8C 63 DB 11 6B
|
||||
AB 25 B0 CC 0D C3 F4 28 0A 4D F9 C3 C5 55 10 D3
|
||||
FE CA 74 07 47 74 3B 60 75 16 22 8B AF C1 C9 30
|
||||
BE BE 13 B3 A8 94 D5 32 81 A5 65 77 08 B8 65 BD
|
||||
BF 73 6C 1C C2 F4 27 41 30 8B 2E 2F 3D 0B 44 71
|
||||
32 AA 6A 4B C3 B5 CE B3 0B 04 AB 4A CB 82 A6 5D
|
||||
6E FE 07 95 C1 4A 63 49 22 D8 FB 3C 79 CD A6 19
|
||||
76 F9 F2 4F 26 C1 90 DD E0 8E C5 D0 74 8E 60 3A
|
||||
3A E2 4F F1 52 CB 0B 53 B7 C6 DE 3D 11 40 E6 F8
|
||||
35 A6 D4 74 93 F9 E3 BB 18 8B 3C 57 3A 7B 49 B5
|
||||
1E 76 18 44 5F E5 5F 67 08 DC 58 97 F5 99 A7 6A
|
||||
A9 D8 F1 BC A6 0B 59 18 0C 3F 52 85 E5 C8 68 18
|
||||
2C D9 84 80 D0 38 1F E4 4E 1E 0A 4F 85 B2 E0 53
|
||||
39 CA 1D 58 1F 8E 35 41 B1 5A 38 5C F4 11 6E 7D
|
||||
2D 75 81 4E 6F 3B 65 2E D7 9E 76 55 8A 69 25 90
|
||||
BD 4B 7C 74 D1 43 22 5A 42 C6 70 D2 55 0F 02 FF
|
||||
25 27 59 41 64 3E 7B 90 5C 32 B8 D7 47 08 E7 EB
|
||||
1E 45 51 E8 FE BF BC DD BB 8B 49 B1 73 D3 91 34
|
||||
C7 2B AD 49 0E 9C 58 F5 24 AF C8 2B 16 3B AA DF
|
||||
52 2F A6 BD 06 2E B5 3F 95 9E 36 A8 78 12 DD BA
|
||||
17 76 19 24 84 2A C2 F0 E8 36 64 47 A6 42 B7 58
|
||||
AD 4C AC 32 FE 00 52 BC 38 C1 8C BD A2 F4 56 5F
|
||||
50 35 02 52 0C BB 79 50 E3 FF 3C 65 D1 E9 9C CC
|
||||
F5 65 CE 6E DF 8D 9A 67 BE BC 8D 45 1B 45 47 98
|
||||
FB EE 52 0D D2 11 26 C1 03 DF B7 8F 66 AC AC 73
|
||||
F8 7E 92 53 F5 EE A5 C1 06 FC E2 5C 5E 2B 79 6F
|
||||
56 F6 C5 A5 64 49 F4 05 66 D8 CD 21 FD 57 8D C9
|
||||
91 10 43 5A FE C2 9B 26 68 4B 23 22 87 87 20 22
|
||||
4F 38 7C F7 30 0A B3 0F 46 C7 E5 B3 9D B5 06 13
|
||||
3F F7 FA 9C 4C 9B 1D CD 61 51 2F 6D D3 D3 B5 9E
|
||||
A7 3B 9E 5B F6 4A 7E F1 37 B5 88 21 F1 73 D1 0E
|
||||
B3 7F 60 9C A9 D7 FB 16 FE 0E E3 0D A0 E8 D3 62
|
||||
8C A1 AC AB AA E2 86 A8 94 03 3F 52 A4 F5 92 C7
|
||||
27 68 C1 5F 40 25 1E F7 F8 15 E5 9C E9 17 33 E5
|
||||
89 FC A2 7A AE 01 BB 9D D4 12 A2 0E 35 7A 49 E9
|
||||
64 18 E3 C7 FA EB D7 45 5B 91 F1 62 D8 3D B6 CC
|
||||
BC 34 6B 34 4C 6D D3 76 8B 71 2B 66 35 16 78 CB
|
||||
AD 6D DC 3C 5B B5 30 8B 64 73 69 43 E2 56 A3 A3
|
||||
5A AD FB 8A 1C 27 53 D3 61 62 64 15 9C F5 7A AC
|
||||
43 B1 B1 BA B3 E7 50 BE 38 EE 3F 16 D3 04 77 27
|
||||
21 39 AF CB 32 2A 7F 53 1C 9E 98 5D 1E 5C E5 C6
|
||||
19 25 05 94 65 48 F4 98 30 92 F2 13 8B 41 99 C4
|
||||
3E C1 4D 78 79 91 18 06 00 1C AC D4 30 C0 8B 2B
|
||||
42 14 55 58 DA 1A 5A AE 85 D4 66 9E 3D FE CD F3
|
||||
AE 08 82 99 D3 46 AA 41 D8 CA 02 47 18 4A C8 52
|
||||
E9 BD CA E0 43 C4 8D A0 A7 3F 89 26 67 36 98 50
|
||||
D3 9D BF 7A 68 F4 54 2A 0E FA 81 98 78 A0 F7 9C
|
||||
F1 DA E6 24 B2 A2 31 78 0F 9C 75 37 E7 DB 4E 28
|
||||
FF C3 58 67 6D 66 B1 9E F7 C3 8A 8F 08 DF 23 6D
|
||||
EB 20 CC 1D E3 95 EB BF 3A 1D 2F 7D 59 35 BF A6
|
||||
9F CE 4A 89 51 E5 3A 39 E9 C1 BC FA FC A9 CA FE
|
||||
5E 3E 4A B2 BE 55 86 73 7A 3F DE E7 E1 66 31 55
|
||||
11 5B 35 C4 D6 7E 88 CF AE A6 B6 F9 1B 8E 1F 6B
|
||||
C8 CB 64 CC D5 E1 2B D5 12 6F 10 38 94 20 A1 72
|
||||
04 D1 4F CF 01 63 92 7C DA 09 04 23 74 44 A1 2F
|
||||
0E 83 88 80 DD 71 B3 49 10 49 ED 96 97 4D C3 55
|
||||
32 59 50 83 D9 1D AC 0A 62 67 BA 35 F2 3E E2 A0
|
||||
26 7B EC 14 BF 6E F3 53 DF 32 99 78 B1 D2 C1 AE
|
||||
B3 F3 9C B1 24 45 D3 59 6F 78 D8 99 06 30 E4 44
|
||||
58 3B EB D0 AD CC 10 40 8D F7 32 1F BF 92 0A BA
|
||||
56 00 57 96 05 BF 5B 40 7D A1 2D 2F 8E E2 F4 73
|
||||
8C E5 64 AE 93 64 4A AD 01 16 75 09 77 B2 A6 7B
|
||||
BB 25 11 DB 66 DC 4D C7 3D 78 CC FE 9D 48 D6 B4
|
||||
D6 0F 3D 27 C6 D9 FE 50 49 24 1C 41 F1 2C C8 42
|
||||
F6 29 9A 8F 24 FF 26 16 41 32 C3 C4 8C D2 66 8D
|
||||
D5 C0 3A 92 E9 05 EA B8 9F 1B 55 E0 3E C1 04 F0
|
||||
3F 0B 1E 0A 83 7D D0 CF 1F DA 38 DA 70 46 5C A7
|
||||
4F 53 F8 8A 83 9B B0 B5 C9 3D 84 CE 65 6C ED 7F
|
||||
C5 B6 69 34 38 F7 B0 D8 B7 94 92 2F 19 53 BD E9
|
||||
48 58 51 0A FA 7D BF CC 0B 29 6C 69 3A 5A CB 20
|
||||
F4 E4 48 02 EC 0B E0 C8 42 DE 88 91 71 A8 45 20
|
||||
A8 73 4C E0 22 D0 B0 56 85 AC CF B8 51 AE F3 90
|
||||
32 62 E3 07 90 47 47 F2 19 60 60 C5 FA CB 23 EA
|
||||
EB 10 BD 5E 5F 8E B0 91 33 E2 CD ED D2 FA 51 53
|
||||
1E A3 68 10 72 91 D6 DF 14 B1 7F C6 78 59 AD 46
|
||||
63 78 27 9E AA E8 86 00 73 9F 1D 8C C7 69 32 F5
|
||||
65 09 F9 90 89 3B AA AC 6C 7C E3 B9 C6 74 13 22
|
||||
01 CF 83 66 64 AA FC 69 2F BF 9C 2C 1E CA 7F 0E
|
||||
CB D5 28 1E 4E ED CC 2C 62 04 03 F2 A3 F4 E6 A3
|
||||
3D 5C 7E 64 B6 45 29 48 AE 96 80 C9 82 82 D5 93
|
||||
B8 38 AF 6D 79 2F F7 C8 A6 E8 23 FA 3E 10 AB 68
|
||||
C6 17 54 04 8F 33 95 5A 3B 02 5F D6 E0 88 82 0B
|
||||
E1 86 D8 60 FD 1E 6B D4 30 30 0D 49 15 09 4B 16
|
||||
73 AC 2E A1 C6 11 59 C0 63 A6 7E 1E 35 64 65 DD
|
||||
53 39 67 0F 37 D0 F4 31 67 1D 6C 1D DE B0 E4 8D
|
||||
11 ED B3 02 33 65 52 7F 61 DC 1B 29 09 16 F0 27
|
||||
C2 E7 D0 A5 07 02 B2 01 83 47 6C 23 77 2B CC EF
|
||||
CD 74 2C 89 95 F2 49 6B 21 7E F6 E0 49 15 9E 85
|
||||
A4 A2 D5 FB 78 55 37 0D 30 0F 2B 76 7D 08 8E 7E
|
||||
20 38 4B 53 A7 6C 90 1E 71 9F F4 76 BD 80 C4 91
|
||||
75 E8 E2 78 0D 40 24 40 B7 1C BF 3D 15 A2 47 88
|
||||
25 5F F5 69 14 29 CC DD 0A B4 07 4B 79 1A 46 9F
|
||||
51 05 E4 BA C4 46 8C 0C 6A FD FC C6 7A 0A 97 8F
|
||||
02 5D 41 83 C1 E1 58 47 5A C8 DB 28 D7 6D 72 0C
|
||||
03 DF D0 AB 6C A6 16 06 D7 EA 8A 06 44 51 1B B8
|
||||
93 6F 5B B3 10 F2 0A 2E C8 F0 2F 48 8B 06 FD C6
|
||||
A3 B0 E3 66 48 CA 53 DA A0 3C 4F 4B F5 0F 90 1C
|
||||
9C A8 72 00 C9 11 D7 AD 09 20 21 46 4F 92 80 D1
|
||||
10 31 62 77 33 68 A5 9F DD 4A DF 39 3C C2 48 31
|
||||
AE 8E B0 DA C0 10 1F 5F D4 AA F4 21 71 81 85 1D
|
||||
05 A7 7D E9 08 B3 6B AA 99 8C E4 F3 0D 90 F0 F1
|
||||
8B 74 59 60 9B 87 4E 75 9E CA B8 57 45 98 70 0B
|
||||
C3 EF 4C F2 D5 59 B7 13 B1 E4 26 EF 6A F4 E5 B5
|
||||
71 89 E5 D8 F5 E1 82 2A 0E 15 E4 31 71 78 AA FB
|
||||
0E D7 40 D7 91 AC D5 27 DD E5 0C 16 6A B1 E7 0F
|
||||
07 30 8F 9C 38 2A C9 91 D4 35 E5 41 6F 3B C5 FB
|
||||
05 A2 9F C6 66 98 2E 49 04 4F 4F C3 22 73 61 3E
|
||||
EA 8D 52 6E 5D 1F B4 87 69 65 C5 FD 98 A8 06 22
|
||||
26 01 AC F1 38 47 18 C0 6B DC 97 F9 67 66 3C 5D
|
||||
84 5C E1 72 F3 11 48 60 D3 2D 1C A9 74 31 8B AB
|
||||
E9 F3 91 9D 01 C1 EF 50 08 BA 50 F4 0E 64 A5 F2
|
||||
2A A1 55 4E F9 92 EA E4 66 AE 70 3F D8 54 63 54
|
||||
85 2F D7 C0 9D EE ED 74 5D 4A BE C4 F2 56 D6 BC
|
||||
3D F9 A9 9C 3E 17 C1 AC 01 AC E9 39 E5 79 4E EA
|
||||
BA 89 4F 01 C7 B2 45 37 93 EB EC 50 5F DF B0 73
|
||||
D3 13 87 CB C1 A6 65 20 70 1E E8 2E AF A8 68 64
|
||||
EC 38 6D 07 28 9B 02 06 4F 79 ED EC 64 3C 4A 26
|
||||
21 E2 B9 22 B2 21 15 6C 8A 39 FC 87 EF D2 A2 F7
|
||||
39 3B 8E BD C9 E6 86 71 7E AA 01 0F 40 5D B2 34
|
||||
1B 91 14 11 E2 0D EC D6 32 D7 4F D3 B6 6B 8B AE
|
||||
FA 2A AA 2D 3F 29 BE 75 67 1C AA F2 39 43 FF 8B
|
||||
79 46 2E 81 C3 32 2C 77 A8 31 C9 09 E9 52 D8 4D
|
||||
14 B5 D3 D4 79 8A 21 14 24 84 5C BD 2A B0 05 11
|
||||
36 D9 30 BE 67 FA 39 79 FB 6F 80 20 81 F3 12 32
|
||||
BD B7 63 8F 6E BC F9 70 FB 00 76 F8 8F 7F A3 CF
|
||||
73 11 77 04 13 9C C4 4B 02 51 5A 28 9F 6F 72 06
|
||||
A2 C3 AE 2E 3C 4C A3 7F 65 58 B9 6B AC D5 D9 6D
|
||||
54 24 FD 54 F5 DA AE 77 EF D3 60 F5 07 B5 0C D7
|
||||
C4 3D 9C 2F 91 23 F0 F0 A8 8A 5B 92 93 AD D3 82
|
||||
36 6C EF E0 7C 17 91 43 9A 7C 78 8A B0 03 E3 A0
|
||||
15 FA FD E9 61 E2 6F 3C 24 84 24 CD 23 9E 4C 4E
|
||||
A6 23 ED 66 76 DF 7C 9E E7 C8 02 F5 1F 1D 0C E4
|
||||
5F 0D A9 06 FB D8 4A 55 8C BB 46 D6 FF 0B 3C 7E
|
||||
13 81 91 22 D8 08 58 EC 56 7B 48 27 59 85 E5 28
|
||||
6C 85 4A 6D 96 3D 83 D6 A2 73 E9 BA 61 60 41 39
|
||||
F5 EA A1 BC 91 36 E4 FA DF 8E E0 D9 1C 33 37 45
|
||||
59 68 FF 42 BF 43 CB CD 7E 4B B7 11 34 17 2F 5C
|
||||
0E 2F 34 A8 57 A7 7C 20 95 BC C3 F8 B5 2E 52 24
|
||||
51 E5 4B BA 70 7E E0 51 21 49 AF AD B6 EC 5F 42
|
||||
05 D7 61 5A 02 43 D4 C5 24 0A 15 C7 C7 7D 43 92
|
||||
A5 FC 1A 97 8D 45 7F 1F 5D 0C 80 1C 13 7E BD 6E
|
||||
FE 25 FC C6 38 AE 9E 59 82 A2 6F 9F BF 3D 65 C8
|
||||
A7 B6 0D 46 8A 38 62 CC AD 7A 3C AA D9 8C 31 7E
|
||||
97 20 F0 5E 96 31 4B 24 CC 4F 97 AF B3 0C 4E 6E
|
||||
C8 C3 CF 10 78 38 F7 29 BD F6 D7 86 F5 55 1B 86
|
||||
00 51 D0 4C C9 EF B4 1F A5 60 1A AE 3E 87 E4 F3
|
||||
30 62 D7 97 6A A0 26 B9 AE 76 CD 1E E7 92 4E 3C
|
||||
F8 78 3E 9E E5 7A 28 9D 31 6B 2D 25 D6 79 EE F8
|
||||
BE FF 5B 44 A6 30 EC B0 64 66 02 92 C2 E1 13 B9
|
||||
0C 67 85 DB 31 CC F7 9F CA 60 DC 39 74 EA 4B EF
|
||||
F5 9A D8 C3 71 85 72 1D CA C6 43 5F A7 94 3D E0
|
||||
9D FA 15 54 41 28 D2 C8 15 2B 38 C8 91 B7 B3 C2
|
||||
EA 6F 71 4E 5D A7 2F 5C 88 1E 69 F2 4B 9F 82 C2
|
||||
68 0C 41 0D F3 59 E1 15 5D 58 B5 89 2F 4E 26 C9
|
||||
27 BF AC 92 7A 7E 22 53 31 FC 13 02 50 D5 F6 00
|
||||
51 05 9A C2 4F FE B7 B5 29 B8 53 A0 5D 1C 0B 33
|
||||
D9 47 D1 B0 EF 90 90 36 A4 E3 2B 20 31 B6 5A 5E
|
||||
78 F3 01 B3 AC CE AC 57 B6 47 46 13 FD A9 C2 DB
|
||||
EC 48 EF 1E 02 14 4F 0C B3 8D B9 05 66 E2 3B D0
|
||||
EC F4 4B 99 2C B4 02 2A 5E 17 4C 14 BE 3B EF CD
|
||||
AF 75 C3 7A 2D F9 33 3C D3 78 71 8F B3 BB 97 48
|
||||
D9 0C 24 17 14 37 40 C8 8A 5B 3D 64 B1 60 A0 83
|
||||
95 25 18 9C 42 10 6D 94 08 E6 78 CD C7 CB F9 1B
|
||||
64 8A 7D 37 6E 35 D0 FB A6 12 65 C7 97 16 A8 3B
|
||||
D2 55 1D 4D 29 D4 D6 05 9B 9C 2E F1 5E 28 41 9F
|
||||
8A 81 ED 54 0F 9C 6B A1 0B EA D1 2E 44 DF B1 C6
|
||||
5E FB 8D E9 C5 FF 25 0A F3 A8 63 C4 54 4A E2 8F
|
||||
54 4F 3F A0 10 3C 07 5B 57 7D AD 00 98 C9 EF F2
|
||||
D2 6C 4A 8F EA 25 31 EF 52 E5 C5 1F D7 66 7C DC
|
||||
05 7E 5D 09 95 94 4C EB 52 1E 30 68 5D 03 45 BE
|
||||
69 E8 47 AE 0D 08 5A 91 32 3F 1B 68 72 81 B3 F1
|
||||
0E 7E BD 95 21 9E E6 95 52 C9 A0 1A 68 CA EE 6B
|
||||
5A 33 A2 81 25 D6 79 7A C3 A1 D6 5F 2D DB 3F A1
|
||||
8E B4 5D 28 A7 A6 BC 70 C8 C4 6E C8 37 D1 48 B5
|
||||
D4 00 27 FE 38 4B 88 17 C9 BE 2B 45 69 50 56 FA
|
||||
89 E8 AE A7 E1 6F 20 C5 FA 96 FF 21 AE 57 61 D0
|
||||
7D 39 C2 FD C4 BF 78 CB 84 C3 AB 7E 7B 4F 5D 30
|
||||
24 93 B5 95 8A 7C 3D FD 3B 32 09 76 8C 80 4B 3D
|
||||
55 FF FE 1A 65 EB BA B3 EE 28 7D 30 A9 C2 CF 12
|
||||
4B 0E 98 7F 9D CB 84 AB 29 1C 8E 9C 7C E8 E4 98
|
||||
A7 9F 08 E3 CC 92 06 68 C1 15 47 4F 13 7A B5 56
|
||||
70 37 F5 08 DE 24 B8 0E AA 6C 8E EF 5B 46 52 F2
|
||||
27 FE 68 D8 7F F2 07 B0 59 9D 1C 1F 9D 9E FE 8E
|
||||
51 A4 33 56 39 47 CF B1 C0 69 CB F4 26 8B 95 20
|
||||
7E 44 91 C1 B4 DB 35 E7 91 CF E3 6A 38 D3 F2 07
|
||||
75 28 BC 9E C4 00 8B 57 10 47 DB 15 36 0D 67 F9
|
||||
03 4E 75 A3 07 61 8B 4A A9 A8 3B A6 8D 53 E3 8C
|
||||
F5 7B DE EF 4D 2B 82 2E AC 79 82 0C F3 D6 09 C7
|
||||
B6 8D EE 90 67 4F E5 99 0C 29 16 35 2F EA AE C2
|
||||
B7 F6 B8 52 28 A9 06 3D F0 6E BA 72 0B 00 87 2D
|
||||
DE 3A 5E 72 6F CC C1 F5 7C ED 79 E2 D6 18 68 F6
|
||||
9F 5B 61 96 02 96 E5 53 E6 B3 84 ED A0 99 7D 58
|
||||
14 13 74 B8 14 4C AB 4B 69 51 90 BF 4B 80 D0 74
|
||||
F2 5C 52 5A 05 3A 16 61 23 66 63 E9 1F A4 0A FF
|
||||
86 A0 F0 C7 8B 78 2C 5B 27 7A 91 CF 75 3C 08 68
|
||||
53 02 D2 C8 A6 E0 5A 30 19 FA 58 6D 7B F1 EA C3
|
||||
1B 81 8F 39 0D 5F F4 BB 6C 08 C3 69 D8 E6 35 45
|
||||
31 3B 5C 29 45 8E D3 B5 68 B7 96 E1 0C 91 B5 C5
|
||||
00 FA 6E D7 D4 5F CE CC 37 EA 46 C6 A1 DA 37 2F
|
||||
44 9B 2A F2 63 95 B0 48 2F CE 6A D9 1E AA 5A 3E
|
||||
97 0E D0 22 09 40 C5 4B B4 3F 86 D4 19 85 5D 25
|
||||
DE 7B CA 30 A1 00 55 77 BA BB 6A 62 C1 01 0A FA
|
||||
FE 35 27 80 FF CF 26 D7 0F 23 C9 F4 5F F9 3A C8
|
||||
1A 41 CE 8F 93 18 16 D0 B1 E1 7F E9 F3 8C B6 4D
|
||||
EA B3 EA A9 32 0E 12 5D C6 16 CB A2 79 8F C5 15
|
||||
72 36 2E 1B B0 2C EC F9 60 97 17 CD 0B E6 CC 88
|
||||
6E 8B 8E 6D D5 05 57 1D 5D 4D 3B 2C F6 D5 FB 0F
|
||||
A1 85 22 90 FD EE 29 BF 13 19 61 F3 1F 21 FB A9
|
||||
CE C6 BD 88 95 40 61 B2 00 58 71 30 90 AB D7 1A
|
||||
56 BE 38 63 F1 E5 02 19 4E 31 4E EB 42 C5 2C 4F
|
||||
AF 8A 6E F6 62 A5 67 89 8C 89 63 8A 4A 6B F9 25
|
||||
EB 8C 1A D0 61 92 68 46 DB 09 0E D1 9C BF 1D 56
|
||||
54 ED BC DD 4F 81 87 F6 4A 28 A7 D1 25 A6 77 99
|
||||
BB 42 1D AC 3C 0B EA 64 0B FA A5 B3 58 8F 4E E9
|
||||
29 70 B6 6C 7F 30 DB 6E 23 DE BC 62 82 38 61 9A
|
||||
69 E8 F9 0B 00 D9 15 A9 36 7A D0 C2 A6 C1 83 F9
|
||||
53 D5 F9 F2 96 4A E7 E7 FF 9D D5 4D 41 39 8E 4C
|
||||
2F 23 7E 2C C7 90 F1 64 EF CA 40 4F E1 16 8D 5D
|
||||
29 A2 AD 1D 60 07 42 37 0D 8A 2F DD 61 78 A6 EC
|
||||
8D CE 9D 77 5F 34 14 48 6A 68 9E 9A 52 21 5B F8
|
||||
FF EA B5 E7 18 BA C5 4C 51 DF 21 0C 90 E0 AE DF
|
||||
25 75 22 CB 8F 76 85 7E 56 07 47 17 7D 47 DB 82
|
||||
FD 63 1E 29 40 BD 86 99 E7 71 90 A3 77 CC 64 9E
|
||||
FB 09 F7 64 A1 9E D9 FD 60 DF A5 15 10 46 39 47
|
||||
4E 39 00 49 62 9B 5D 4D C2 5F 3E 63 6D 5F 94 99
|
||||
F3 C2 7A 03 7B AA E3 35 A1 1C 11 BA 7D EE 0A B4
|
||||
66 4A B4 D6 7D 37 AD A9 6B AA 36 D9 FE 45 78 08
|
||||
E6 08 20 7D E5 7E 20 33 C7 7B 9C B4 51 FA D2 35
|
||||
7F 66 E4 50 51 D3 82 C0 7D 5F AD 5E EA A3 05 2D
|
||||
2B 3A D8 35 65 D4 12 C5 B0 D5 7E 98 1D 0D 45 31
|
||||
D1 85 08 EE 9F B1 D7 0A E3 3F 9C 3A 99 3E EC 8B
|
||||
71 5E BA 18 F0 91 09 37 BF FE F6 BE F9 A0 C3 57
|
||||
65 B1 C9 30 FC 6E 7D 2A 40 34 1B DE 86 52 E5 90
|
||||
61 C9 6A 23 5D ED D5 38 DE AD 17 7E F7 B0 C4 32
|
||||
43 EE 16 E5 5C 99 68 40 B6 EA 2A DE 12 14 19 4F
|
||||
2A F1 68 03 4F 01 D9 65 7C C7 C3 79 B6 BF 75 EF
|
||||
CF 13 FE 07 63 B4 0C FC BA 43 D6 BC B1 D6 EA F5
|
||||
95 E8 AA 3B 42 AE 7B B7 71 71 32 BD 67 BB 95 98
|
||||
6D A3 44 E0 60 C8 7D 78 92 9E 9C 71 17 FC 11 EF
|
||||
C4 72 13 30 55 31 76 81 1B 0E 66 AE 7E E2 DD D6
|
||||
F0 B1 74 6E E3 42 00 DA 12 0A 2F 3D 08 ED 11 0C
|
||||
D2 49 6A 43 2A BC 44 E2 D7 87 70 37 80 61 CB 06
|
||||
72 F7 56 10 47 7B 0D 89 35 07 A8 7C DC 40 52 0A
|
||||
0B 39 9C 97 81 CB F7 94 5B 55 AA 61 5A 43 7D E7
|
||||
C7 4D 38 8F 08 32 81 74 75 9F 03 F3 6A DD 86 28
|
||||
20 AB 2F EA 5C A2 AC 2B EF 29 BA 14 C8 0D 02 BA
|
||||
39 66 97 9B 8C 78 5C F2 DB 78 27 C2 6A 2A CC 88
|
||||
1A 4A AC 38 DC 37 91 96 EF 50 6C CD F7 68 AE 61
|
||||
4C 14 95 66 DE 49 99 71 94 D0 99 5E 92 5D 52 1B
|
||||
EA 17 EE D6 47 1D C8 7E B3 87 60 B0 87 2F FB E3
|
||||
15 DD B5 4F 39 A6 ED 0B 8B 27 7F 1E 0E 21 86 6F
|
||||
CF 60 B8 95 D0 49 AD 5E FD 5D F0 1D C1 DF E7 52
|
||||
4D 2B 52 FC C9 C3 F7 EB 83 B4 D2 97 7D FC AF 11
|
||||
53 70 F8 90 0D D2 0F 88 66 9A 4F 7B 55 2A 7B E8
|
||||
EA 79 11 4E 29 91 2F A3 D3 2D 32 CF 60 41 A2 C4
|
||||
C5 34 27 F2 E7 B0 3C 84 2C 9B 29 1C C5 FA 4F 24
|
||||
24 30 F4 9B 35 AE 66 17 67 70 EF 32 1A 8F 3F 1E
|
||||
92 5E 15 15 40 54 41 71 8D 6E 9D C1 4C E3 7E 4D
|
||||
C3 33 9C 70 7A F2 5D F4 26 3A D2 B3 9B E3 25 00
|
||||
ED CC AA 6E 0D 44 91 DA 6E CE 86 5F 45 75 E3 90
|
||||
0D 70 77 0A B7 EC 87 70 0D 49 BA 6F 76 7C 64 C8
|
||||
3C 5B 4B D7 B7 39 AE 92 62 A3 3D 47 44 83 94 63
|
||||
34 AE 1B EB 51 29 C8 17 D9 4C E9 40 77 42 81 A6
|
||||
18 0C 49 30 28 8F 28 0D 76 B3 0A 4F CA 12 E8 84
|
||||
95 0F D7 27 49 24 2E 3D EF 7F 5B 8E 48 D3 AE 17
|
||||
6E 87 C7 09 A6 51 7C E1 AD FC 28 CE FB 0C CA 1C
|
||||
06 F6 BC 10 1F 71 30 B5 CD A9 BD C2 21 58 09 32
|
||||
63 45 CA 59 5E F4 3B 25 44 8E 1B B3 7E 73 E7 BD
|
||||
49 65 18 17 A2 FF 65 B5 0B FF 69 5E EB 7A 96 19
|
||||
4F 44 FB 18 FF 23 D9 78 15 8F 47 4D 4C 9E C1 34
|
||||
E9 24 E9 DD 8C CF 1D 0C CE 8C CB 46 3F 4F 63 C2
|
||||
61 AB 61 F7 94 1D A9 E4 A0 C0 19 D5 8F 45 E7 37
|
||||
A9 3D C7 47 94 CF 84 B3 83 77 20 0D 16 59 BE A7
|
||||
95 8D AA D3 15 31 4D 0B CC 73 77 03 7C F3 D9 09
|
||||
A1 7C CA EA F2 A2 30 87 03 9B E6 29 6D 3A E9 AE
|
||||
8F 72 00 F9 CE 74 C5 55 2C 1C 4C 28 3C C4 FA 7D
|
||||
B8 43 88 0E 3E 98 5C B5 81 9C 2F AD E0 CB DD D4
|
||||
DB 45 28 A6 90 E8 13 9D 5C DA F1 4C BB 67 15 EF
|
||||
9C 9B EA 7E 01 48 AE F2 84 00 00 6C C4 13 67 61
|
||||
A6 C2 20 2A 61 14 41 38 57 3A D1 94 DD 7B B8 54
|
||||
84 77 04 06 BF 88 D7 C1 D3 CA 9F 03 E8 91 C3 02
|
||||
F3 F9 73 E9 E7 79 31 BD 25 3A 1E DD 32 82 64 36
|
||||
02 EA A2 69 2C 9A A4 2F 43 13 08 9A B1 24 91 86
|
||||
15 2D D4 5A 69 65 B5 23 AF AF FB 9D DB 44 C3 E7
|
||||
83 44 08 B1 93 9C 7D 0D 75 8F 45 FD 06 99 79 60
|
||||
61 0F 9A A1 E4 60 77 D4 2F 76 66 FA 8B A6 81 8E
|
||||
* End 138167944 2957739639
|
||||
@ -30,57 +30,60 @@ WIRE -544 -432 -544 -560
|
||||
WIRE -384 -432 -544 -432
|
||||
WIRE -16 -432 -16 -560
|
||||
WIRE -16 -432 -320 -432
|
||||
WIRE -1600 -400 -1600 -496
|
||||
WIRE -1600 -320 -1600 -496
|
||||
WIRE -880 -320 -880 -336
|
||||
WIRE -800 -320 -800 -368
|
||||
WIRE -1600 -288 -1600 -320
|
||||
WIRE -1648 -256 -1840 -256
|
||||
WIRE -1840 -240 -1840 -256
|
||||
WIRE -1600 -208 -1600 -240
|
||||
WIRE 752 -208 752 -560
|
||||
WIRE -1600 -176 -1600 -208
|
||||
WIRE 240 -144 208 -144
|
||||
WIRE 512 -144 304 -144
|
||||
WIRE 704 -128 592 -128
|
||||
WIRE -1600 -112 -1600 -208
|
||||
WIRE 208 -80 208 -144
|
||||
WIRE 208 -80 96 -80
|
||||
WIRE 352 -80 208 -80
|
||||
WIRE 512 -80 512 -144
|
||||
WIRE 512 -80 480 -80
|
||||
WIRE 656 -80 512 -80
|
||||
WIRE -1600 -64 -1600 -112
|
||||
WIRE -1600 -64 -1728 -64
|
||||
WIRE -1600 -64 -1600 -96
|
||||
WIRE 656 -64 656 -80
|
||||
WIRE -1600 -48 -1600 -64
|
||||
WIRE -1728 -16 -1728 -64
|
||||
WIRE 352 -16 320 -16
|
||||
WIRE 592 -16 592 -128
|
||||
WIRE 592 -16 480 -16
|
||||
WIRE 320 0 320 -16
|
||||
WIRE -1600 48 -1600 32
|
||||
WIRE 352 48 96 48
|
||||
WIRE 656 48 656 0
|
||||
WIRE 656 48 480 48
|
||||
WIRE 752 48 752 -112
|
||||
WIRE 752 48 656 48
|
||||
WIRE 976 48 752 48
|
||||
WIRE -1600 80 -1600 16
|
||||
WIRE -1600 80 -1728 80
|
||||
WIRE -1600 96 -1600 80
|
||||
WIRE 752 96 752 48
|
||||
WIRE -1728 128 -1728 48
|
||||
WIRE -1728 128 -1728 80
|
||||
WIRE 976 128 976 48
|
||||
WIRE 96 144 96 48
|
||||
WIRE -1600 192 -1600 176
|
||||
WIRE 752 208 752 176
|
||||
WIRE 848 208 752 208
|
||||
WIRE 752 240 752 208
|
||||
WIRE 848 256 848 208
|
||||
WIRE -1728 272 -1728 192
|
||||
WIRE 752 384 752 320
|
||||
WIRE 848 384 848 320
|
||||
WIRE 976 384 976 192
|
||||
FLAG 752 384 0
|
||||
FLAG -1600 128 0
|
||||
FLAG -1600 272 0
|
||||
FLAG 96 224 0
|
||||
FLAG -1600 -560 vbus
|
||||
FLAG -992 -560 vmid
|
||||
FLAG 848 384 0
|
||||
FLAG -1680 -416 0
|
||||
FLAG -1600 -112 vdrv
|
||||
FLAG -1728 128 0
|
||||
FLAG -1600 -208 vdrv
|
||||
FLAG -1728 272 0
|
||||
FLAG 320 0 0
|
||||
FLAG 96 -80 cp
|
||||
FLAG 96 0 0
|
||||
@ -91,17 +94,19 @@ FLAG 976 384 0
|
||||
FLAG -800 -320 0
|
||||
FLAG 400 -320 0
|
||||
FLAG -880 -320 0
|
||||
FLAG -1648 -304 0
|
||||
FLAG -1840 -160 0
|
||||
SYMBOL nmos 704 -208 R0
|
||||
SYMATTR InstName M1
|
||||
SYMATTR Value AON7140
|
||||
SYMBOL res 736 224 R0
|
||||
SYMATTR InstName R1
|
||||
SYMATTR Value {rtip}
|
||||
SYMBOL voltage -1600 32 R0
|
||||
SYMBOL voltage -1600 176 R0
|
||||
WINDOW 123 0 0 Left 0
|
||||
WINDOW 39 24 44 Left 2
|
||||
SYMATTR InstName V1
|
||||
SYMATTR Value PWL(0 0 1m 0 1.1m {vbus} 10m {vbus} 10.1m 0)
|
||||
SYMATTR Value {vbus}
|
||||
SYMBOL voltage 96 128 R0
|
||||
WINDOW 123 0 0 Left 0
|
||||
WINDOW 39 0 0 Left 0
|
||||
@ -118,20 +123,20 @@ SYMATTR Value 5m
|
||||
SYMBOL cap 832 256 R0
|
||||
SYMATTR InstName C4
|
||||
SYMATTR Value 10p
|
||||
SYMBOL ind -1616 -416 R0
|
||||
SYMBOL ind -1616 -192 R0
|
||||
SYMATTR InstName L2
|
||||
SYMATTR Value 500n
|
||||
SYMATTR SpiceLine Rser=1m
|
||||
SYMBOL res -1616 -304 R0
|
||||
SYMBOL res -1616 -80 R0
|
||||
SYMATTR InstName R8
|
||||
SYMATTR Value 120m
|
||||
SYMBOL cap -1696 -480 R0
|
||||
SYMATTR InstName C5
|
||||
SYMATTR Value 1µ
|
||||
SYMBOL res -1616 -64 R0
|
||||
SYMBOL res -1616 80 R0
|
||||
SYMATTR InstName R9
|
||||
SYMATTR Value 20m
|
||||
SYMBOL cap -1744 -16 R0
|
||||
SYMBOL cap -1744 128 R0
|
||||
SYMATTR InstName C6
|
||||
SYMATTR Value 200µ
|
||||
SYMBOL IRS10752L 416 -48 R0
|
||||
@ -149,15 +154,6 @@ SYMBOL ind 736 80 R0
|
||||
SYMATTR InstName L3
|
||||
SYMATTR Value 10n
|
||||
SYMATTR SpiceLine Rser=1m
|
||||
SYMBOL MCASU32MAB7106_PNA01 80 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U4
|
||||
SYMBOL MCASU32MAB7106_PNA01 192 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U5
|
||||
SYMBOL MCASU32MAB7106_PNA01 288 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U6
|
||||
SYMBOL ind -416 -544 R270
|
||||
WINDOW 0 32 56 VTop 2
|
||||
WINDOW 3 5 56 VBottom 2
|
||||
@ -185,19 +181,36 @@ SYMATTR InstName D1
|
||||
SYMATTR Value RB068M-60
|
||||
SYMBOL Contrib\\CHEMI-CON\\Capacitors\\Alcap-PolymerHybrid-SMD\\HHXC350ARA220ME61G -816 -432 R0
|
||||
SYMATTR InstName C2
|
||||
SYMBOL MCASU32MAB7106_PNA01 400 -384 R90
|
||||
SYMBOL sw -1600 -336 R0
|
||||
SYMATTR InstName S1
|
||||
SYMATTR Value SW1
|
||||
SYMBOL voltage -1840 -256 R0
|
||||
SYMATTR InstName V4
|
||||
SYMATTR Value PWL(0 0 1m 0 1.1m 1 6m 1 6.1m 0)
|
||||
SYMBOL MMASU32MAB7106_PNA01 -880 -400 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U3
|
||||
SYMBOL MMASU32MAB7106_PNA01 80 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U1
|
||||
SYMBOL MCASU32MAB7106_PNA01 -880 -400 R90
|
||||
SYMBOL MMASU32MAB7106_PNA01 192 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U8
|
||||
SYMATTR InstName U4
|
||||
SYMBOL MMASU32MAB7106_PNA01 288 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U5
|
||||
SYMBOL MMASU32MAB7106_PNA01 400 -384 R90
|
||||
SYMATTR Value Temperature=40
|
||||
SYMATTR InstName U6
|
||||
TEXT -1656 -1016 Left 2 !.tran 12m
|
||||
TEXT -1648 -808 Left 2 !.param fsw=100k
|
||||
TEXT -1648 -776 Left 2 !.param d={pout/(vbus*vbus/rtip)}
|
||||
TEXT -1648 -904 Left 2 !.param vbus=28
|
||||
TEXT -1648 -840 Left 2 !.param pout=130
|
||||
TEXT -1648 -872 Left 2 !.param rtip=2.5
|
||||
TEXT -576 -40 Left 2 !.param rtip=2.5
|
||||
TEXT 352 112 Left 2 !.lib IRS10752L.lib
|
||||
TEXT -1648 -936 Left 2 !.param vcc=3.3
|
||||
TEXT -1656 -992 Left 2 !.options abstol=10n vntol=10n reltol=0.005 gmin=10p method=gear
|
||||
TEXT -480 -632 Left 2 !.param L=2.2u Is=7
|
||||
TEXT -584 -64 Left 2 !*.step param rtip list 2.5 3 3.5 4.5 5 100k
|
||||
TEXT -1496 -16 Left 2 !.model SW1 SW(Ron=1n Roff=10Meg Vt=0.5 Vh=0.1)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user