Add package.json and tools listing
This commit is contained in:
parent
b109c29eef
commit
87bd64cf2a
5 changed files with 285 additions and 13 deletions
10
README.md
10
README.md
|
|
@ -4,11 +4,17 @@ Raspberry Pi Pico Arduino core, for all RP2040 boards
|
|||
This is an under-development port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosystem.
|
||||
|
||||
It uses a custom toolset with GCC 10.2 and Newlib 4.0.0, not depending on system-installed prerequisites. https://github.com/earlephilhower/pico-quick-toolchain
|
||||
A `package.json`file needs to be built to enable full integration, so for now some paths are just hardcoded.
|
||||
|
||||
Only delay, analogWrite, and digitalWrite are implemented now. The biggest hurdle was getting a working build system outside of the pick-sdk CMake environment.
|
||||
Presently, a manually build `pico.a` file is generated using objects compiled by `cmake` in the pico-examples repo, but in the future this will be scripted and automated.
|
||||
|
||||
There is automated discovery of boards in bootloader mode, so they show up in the IDE, and the upload command works using the Microsoft UF2 tool (included).
|
||||
|
||||
To install: `mkdir -p ~/Arduino/hardware/pico; git clone https://github.com/earlephilhower/arduino-pico.git ~/Arduino/hardware/pico/rp2040`
|
||||
To install:
|
||||
````
|
||||
mkdir -p ~/Arduino/hardware/pico
|
||||
git clone https://github.com/earlephilhower/arduino-pico.git ~/Arduino/hardware/pico/rp2040
|
||||
cd ~/Arduino/hardware/pico/rp2040/system
|
||||
python3 ./get.py
|
||||
`````
|
||||
|
||||
|
|
|
|||
6
package.json
Normal file
6
package.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "framework-arduinopico",
|
||||
"description": "Arduino Wiring-based Framework (RPi Pico RP2040)",
|
||||
"url": "https://github.com/esrlephilhower/arduino-pico",
|
||||
"version": "0.0.1-dev"
|
||||
}
|
||||
125
package/package_pico_index.template.json
Normal file
125
package/package_pico_index.template.json
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "Raspberry Pi Pico",
|
||||
"maintainer": "Earle F. Philhwoer, III",
|
||||
"websiteURL": "https://github.com/earlephilhower/arduino-pico",
|
||||
"email": "earlephilhower@yahoo.com",
|
||||
"help": {
|
||||
"online": "https://github.com/earlephilhower/arduino-pico"
|
||||
},
|
||||
"platforms": [
|
||||
{
|
||||
"category": "Raspberry Pi Pico",
|
||||
"name": "rpipico",
|
||||
"url": "",
|
||||
"version": "",
|
||||
"architecture": "rp2040",
|
||||
"archiveFileName": "",
|
||||
"boards": [
|
||||
{
|
||||
"name": "Raspberry Pi Pico"
|
||||
}
|
||||
],
|
||||
"toolsDependencies": [
|
||||
{
|
||||
"packager": "efp3",
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-gcc"
|
||||
},
|
||||
{
|
||||
"packager": "efp3",
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-mklittlefs"
|
||||
},
|
||||
{
|
||||
"packager": "efp3",
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-elf2uf2"
|
||||
},
|
||||
{
|
||||
"packager": "efp3",
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-pioasm"
|
||||
},
|
||||
{
|
||||
"packager": "efp3",
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-python3"
|
||||
}
|
||||
],
|
||||
"help": {
|
||||
"online": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-python3",
|
||||
"systems": [
|
||||
{
|
||||
"host": "x86_64-pc-linux-gnu",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/0.0.1-alpha/python3-via-env.tar.gz",
|
||||
"archiveFileName": "python3-via-env.tar.gz",
|
||||
"checksum": "SHA-256:c9237bfe0f62842d7187a39495baa4a7e3ab8b87c0b433614294b023cf0bc0f3",
|
||||
"size": "292"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-gcc",
|
||||
"systems": [
|
||||
{
|
||||
"host": "x86_64-pc-linux-gnu",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/0.0.1-alpha/x86_64-linux-gnu.arm-none-eabi-482adf8.210217.tar.gz",
|
||||
"archiveFileName": "x86_64-linux-gnu.arm-none-eabi-482adf8.210217.tar.gz",
|
||||
"checksum": "SHA-256:9a2e035c8f445c7fe7fe98e67a5b758b6246b13f9461fa3a9db3a4e2a5dfb486",
|
||||
"size": "106268157"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-elf2uf2",
|
||||
"systems": [
|
||||
{
|
||||
"host": "x86_64-pc-linux-gnu",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/0.0.1-alpha/x86_64-linux-gnu.elf2uf2-0f3b795.210217.tar.gz",
|
||||
"archiveFileName": "x86_64-linux-gnu.elf2uf2-0f3b795.210217.tar.gz",
|
||||
"checksum": "SHA-256:ab56df8c2faf286ad0e8e69bc75eaca07ef5467dbf4fcaaa2b8b5bbbdd8e6143",
|
||||
"size": "23974"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-pioasm",
|
||||
"systems": [
|
||||
{
|
||||
"host": "x86_64-pc-linux-gnu",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/0.0.1-alpha/x86_64-linux-gnu.pioasm-0f3b795.210217.tar.gz",
|
||||
"archiveFileName": "x86_64-linux-gnu.pioasm-0f3b795.210217.tar.gz",
|
||||
"checksum": "SHA-256:b058320b912a0f957b1c6121afe64d9ddf370e674bab782e86c5fcdf626b4f0b",
|
||||
"size": "159440"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "pqt-mklittlefs",
|
||||
"systems": [
|
||||
{
|
||||
"host": "x86_64-pc-linux-gnu",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/0.0.1-alpha/x86_64-linux-gnu.mklittlefs-6b5c62d.210217.tar.gz",
|
||||
"archiveFileName": "x86_64-linux-gnu.mklittlefs-6b5c62d.210217.tar.gz",
|
||||
"checksum": "SHA-256:e7bc64beb40386f29f85a02e6ef4b7944d174064d46051402958a47b5a61eb1b",
|
||||
"size": "46930"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
21
platform.txt
21
platform.txt
|
|
@ -21,6 +21,13 @@
|
|||
|
||||
name=Rasperry Pi RP2040 Boards
|
||||
version=1.0.0
|
||||
runtime.tools.pqt-gcc.path={runtime.platform.path}/system/arm-none-eabi
|
||||
runtime.tools.pqt-python3.path={runtime.platform.path}/system/python3
|
||||
runtime.tools.pqt-mklittlefs.path={runtime.platform.path}/system/mklittlefs
|
||||
runtime.tools.pqt-pioasm.path={runtime.platform.path}/system/pioasm
|
||||
runtime.tools.pqt-elf2uf2.path={runtime.platform.path}/system/elf2uf2
|
||||
|
||||
compiler.path={runtime.tools.pqt-gcc.path}/bin/
|
||||
|
||||
# Compile variables
|
||||
# -----------------
|
||||
|
|
@ -36,8 +43,6 @@ compiler.includes=-I{runtime.platform.path}/pico_base/ -I{runtime.platform.path}
|
|||
compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -Os -DNDEBUG -ffunction-sections -fdata-sections
|
||||
compiler.wrap=-Wl,--wrap=acos -Wl,--wrap=acosf -Wl,--wrap=acosh -Wl,--wrap=acoshf -Wl,--wrap=__aeabi_cdcmpeq -Wl,--wrap=__aeabi_cdcmple -Wl,--wrap=__aeabi_cdrcmple -Wl,--wrap=__aeabi_cfcmpeq -Wl,--wrap=__aeabi_cfcmple -Wl,--wrap=__aeabi_cfrcmple -Wl,--wrap=__aeabi_d2f -Wl,--wrap=__aeabi_d2iz -Wl,--wrap=__aeabi_d2lz -Wl,--wrap=__aeabi_d2uiz -Wl,--wrap=__aeabi_d2ulz -Wl,--wrap=__aeabi_dadd -Wl,--wrap=__aeabi_dcmpeq -Wl,--wrap=__aeabi_dcmpge -Wl,--wrap=__aeabi_dcmpgt -Wl,--wrap=__aeabi_dcmple -Wl,--wrap=__aeabi_dcmplt -Wl,--wrap=__aeabi_dcmpun -Wl,--wrap=__aeabi_ddiv -Wl,--wrap=__aeabi_dmul -Wl,--wrap=__aeabi_drsub -Wl,--wrap=__aeabi_dsub -Wl,--wrap=__aeabi_f2d -Wl,--wrap=__aeabi_f2iz -Wl,--wrap=__aeabi_f2lz -Wl,--wrap=__aeabi_f2uiz -Wl,--wrap=__aeabi_f2ulz -Wl,--wrap=__aeabi_fadd -Wl,--wrap=__aeabi_fcmpeq -Wl,--wrap=__aeabi_fcmpge -Wl,--wrap=__aeabi_fcmpgt -Wl,--wrap=__aeabi_fcmple -Wl,--wrap=__aeabi_fcmplt -Wl,--wrap=__aeabi_fcmpun -Wl,--wrap=__aeabi_fdiv -Wl,--wrap=__aeabi_fmul -Wl,--wrap=__aeabi_frsub -Wl,--wrap=__aeabi_fsub -Wl,--wrap=__aeabi_i2d -Wl,--wrap=__aeabi_i2f -Wl,--wrap=__aeabi_idiv -Wl,--wrap=__aeabi_idivmod -Wl,--wrap=__aeabi_l2d -Wl,--wrap=__aeabi_l2f -Wl,--wrap=__aeabi_ldivmod -Wl,--wrap=__aeabi_lmul -Wl,--wrap=__aeabi_memcpy -Wl,--wrap=__aeabi_memcpy4 -Wl,--wrap=__aeabi_memcpy8 -Wl,--wrap=__aeabi_memset -Wl,--wrap=__aeabi_memset4 -Wl,--wrap=__aeabi_memset8 -Wl,--wrap=__aeabi_ui2d -Wl,--wrap=__aeabi_ui2f -Wl,--wrap=__aeabi_uidiv -Wl,--wrap=__aeabi_uidivmod -Wl,--wrap=__aeabi_ul2d -Wl,--wrap=__aeabi_ul2f -Wl,--wrap=__aeabi_uldivmod -Wl,--wrap=asin -Wl,--wrap=asinf -Wl,--wrap=asinh -Wl,--wrap=asinhf -Wl,--wrap=atan -Wl,--wrap=atan2 -Wl,--wrap=atan2f -Wl,--wrap=atanf -Wl,--wrap=atanh -Wl,--wrap=atanhf -Wl,--wrap=calloc -Wl,--wrap=cbrt -Wl,--wrap=cbrtf -Wl,--wrap=ceil -Wl,--wrap=ceilf -Wl,--wrap=__clz -Wl,--wrap=__clzdi2 -Wl,--wrap=__clzl -Wl,--wrap=__clzll -Wl,--wrap=__clzsi2 -Wl,--wrap=copysign -Wl,--wrap=copysignf -Wl,--wrap=cos -Wl,--wrap=cosf -Wl,--wrap=cosh -Wl,--wrap=coshf -Wl,--wrap=__ctzdi2 -Wl,--wrap=__ctzsi2 -Wl,--wrap=drem -Wl,--wrap=dremf -Wl,--wrap=exp -Wl,--wrap=exp10 -Wl,--wrap=exp10f -Wl,--wrap=exp2 -Wl,--wrap=exp2f -Wl,--wrap=expf -Wl,--wrap=expm1 -Wl,--wrap=expm1f -Wl,--wrap=floor -Wl,--wrap=floorf -Wl,--wrap=fma -Wl,--wrap=fmaf -Wl,--wrap=fmod -Wl,--wrap=fmodf -Wl,--wrap=free -Wl,--wrap=hypot -Wl,--wrap=hypotf -Wl,--wrap=ldexp -Wl,--wrap=ldexpf -Wl,--wrap=log -Wl,--wrap=log10 -Wl,--wrap=log10f -Wl,--wrap=log1p -Wl,--wrap=log1pf -Wl,--wrap=log2 -Wl,--wrap=log2f -Wl,--wrap=logf -Wl,--wrap=malloc -Wl,--wrap=memcpy -Wl,--wrap=memset -Wl,--wrap=__popcountdi2 -Wl,--wrap=__popcountsi2 -Wl,--wrap=pow -Wl,--wrap=powf -Wl,--wrap=powint -Wl,--wrap=powintf -Wl,--wrap=printf -Wl,--wrap=putchar -Wl,--wrap=puts -Wl,--wrap=remainder -Wl,--wrap=remainderf -Wl,--wrap=remquo -Wl,--wrap=remquof -Wl,--wrap=round -Wl,--wrap=roundf -Wl,--wrap=sin -Wl,--wrap=sincos -Wl,--wrap=sincosf -Wl,--wrap=sinf -Wl,--wrap=sinh -Wl,--wrap=sinhf -Wl,--wrap=snprintf -Wl,--wrap=sprintf -Wl,--wrap=sqrt -Wl,--wrap=sqrtf -Wl,--wrap=tan -Wl,--wrap=tanf -Wl,--wrap=tanh -Wl,--wrap=tanhf -Wl,--wrap=trunc -Wl,--wrap=truncf -Wl,--wrap=vprintf -Wl,--wrap=vsnprintf
|
||||
|
||||
|
||||
compiler.path=/home/earle/src/pico-quick-toolchain/arm-none-eabi.x86_64/bin/
|
||||
compiler.c.cmd=arm-none-eabi-gcc
|
||||
compiler.c.flags=-c {compiler.defines} {compiler.flags} {compiler.includes}
|
||||
compiler.c.elf.cmd=arm-none-eabi-g++
|
||||
|
|
@ -72,8 +77,7 @@ compiler.S.extra_flags=
|
|||
compiler.ar.extra_flags=
|
||||
compiler.elf2hex.extra_flags=
|
||||
|
||||
|
||||
discovery.rp2040.pattern=python3 "{runtime.platform.path}/system/discovery.py"
|
||||
discovery.rp2040.pattern="python3" "{runtime.platform.path}/system/discovery.py"
|
||||
|
||||
# USB Flags
|
||||
# ---------
|
||||
|
|
@ -103,11 +107,8 @@ recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compil
|
|||
## Combine gc-sections, archives, and objects
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-Wl,--script={build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" {runtime.platform.path}/system/libs/pico.a -lm -I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/ -I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include {runtime.platform.path}/assembly/bs2_default_padded_checksummed.S
|
||||
|
||||
## Create output (bin file)
|
||||
recipe.objcopy.uf2.pattern=/home/earle/src/pico-quick-toolchain/arena.x86_64/elf2uf2/elf2uf2 "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2"
|
||||
|
||||
## Create output (hex file)
|
||||
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
|
||||
## Create output (UF2 file)
|
||||
recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2"
|
||||
|
||||
build.preferred_out_format=uf2
|
||||
|
||||
|
|
@ -124,8 +125,6 @@ tools.uf2conv.path=
|
|||
# Because the variable expansion doesn't allow one tool to find another, the following lines
|
||||
# will point to "{runtime.platform.path}/tools/python3/python3" in GIT and
|
||||
# "{runtime.tools.python3.path}/python3" for JSON board manager releases.
|
||||
#tools.uf2conv.cmd={runtime.tools.python3.path}/python3
|
||||
#tools.uf2conv.network_cmd={runtime.tools.python3.path}/python3
|
||||
tools.uf2conv.cmd=python3
|
||||
tools.uf2conv.network_cmd=python3
|
||||
|
||||
|
|
|
|||
136
system/get.py
Executable file
136
system/get.py
Executable file
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python3
|
||||
# This script will download and extract required tools into the current directory.
|
||||
# Tools list is obtained from package/package_esp8266com_index.template.json file.
|
||||
# Written by Ivan Grokhotkov, 2015.
|
||||
#
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import shutil
|
||||
import errno
|
||||
import os.path
|
||||
import hashlib
|
||||
import json
|
||||
import platform
|
||||
import sys
|
||||
import tarfile
|
||||
import zipfile
|
||||
import re
|
||||
|
||||
verbose = True
|
||||
|
||||
if sys.version_info[0] == 3:
|
||||
from urllib.request import urlretrieve
|
||||
else:
|
||||
# Not Python 3 - today, it is most likely to be Python 2
|
||||
from urllib import urlretrieve
|
||||
|
||||
dist_dir = 'dist/'
|
||||
|
||||
def sha256sum(filename, blocksize=65536):
|
||||
hash = hashlib.sha256()
|
||||
with open(filename, "rb") as f:
|
||||
for block in iter(lambda: f.read(blocksize), b""):
|
||||
hash.update(block)
|
||||
return hash.hexdigest()
|
||||
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST or not os.path.isdir(path):
|
||||
raise
|
||||
|
||||
def report_progress(count, blockSize, totalSize):
|
||||
global verbose
|
||||
if verbose:
|
||||
percent = int(count*blockSize*100/totalSize)
|
||||
percent = min(100, percent)
|
||||
sys.stdout.write("\r%d%%" % percent)
|
||||
sys.stdout.flush()
|
||||
|
||||
def unpack(filename, destination):
|
||||
dirname = ''
|
||||
print('Extracting {0}'.format(filename))
|
||||
if filename.endswith('tar.gz'):
|
||||
tfile = tarfile.open(filename, 'r:gz')
|
||||
tfile.extractall(destination)
|
||||
dirname= tfile.getnames()[0]
|
||||
elif filename.endswith('zip'):
|
||||
zfile = zipfile.ZipFile(filename)
|
||||
zfile.extractall(destination)
|
||||
dirname = zfile.namelist()[0]
|
||||
else:
|
||||
raise NotImplementedError('Unsupported archive type')
|
||||
|
||||
# a little trick to rename tool directories so they don't contain version number
|
||||
rename_to = re.match(r'^([a-zA-Z_][^\-]*\-*)+', dirname).group(0).strip('-')
|
||||
if rename_to != dirname:
|
||||
print('Renaming {0} to {1}'.format(dirname, rename_to))
|
||||
if os.path.isdir(rename_to):
|
||||
shutil.rmtree(rename_to)
|
||||
shutil.move(dirname, rename_to)
|
||||
|
||||
def get_tool(tool):
|
||||
archive_name = tool['archiveFileName']
|
||||
local_path = dist_dir + archive_name
|
||||
url = tool['url']
|
||||
real_hash = tool['checksum'].split(':')[1]
|
||||
if not os.path.isfile(local_path):
|
||||
print('Downloading ' + archive_name);
|
||||
urlretrieve(url, local_path, report_progress)
|
||||
sys.stdout.write("\rDone\n")
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
print('Tool {0} already downloaded'.format(archive_name))
|
||||
local_hash = sha256sum(local_path)
|
||||
if local_hash != real_hash:
|
||||
print('Hash mismatch for {0}, delete the file and try again'.format(local_path))
|
||||
raise RuntimeError()
|
||||
unpack(local_path, '.')
|
||||
|
||||
def load_tools_list(filename, platform):
|
||||
tools_info = json.load(open(filename))['packages'][0]['tools']
|
||||
tools_to_download = []
|
||||
for t in tools_info:
|
||||
tool_platform = [p for p in t['systems'] if p['host'] == platform]
|
||||
if len(tool_platform) == 0:
|
||||
continue
|
||||
tools_to_download.append(tool_platform[0])
|
||||
return tools_to_download
|
||||
|
||||
def identify_platform():
|
||||
arduino_platform_names = {'Darwin' : {32 : 'i386-apple-darwin', 64 : 'x86_64-apple-darwin'},
|
||||
'Linux' : {32 : 'i686-pc-linux-gnu', 64 : 'x86_64-pc-linux-gnu'},
|
||||
'LinuxARM': {32 : 'arm-linux-gnueabihf', 64 : 'aarch64-linux-gnu'},
|
||||
'Windows' : {32 : 'i686-mingw32', 64 : 'x86_64-mingw32'}}
|
||||
bits = 32
|
||||
if sys.maxsize > 2**32:
|
||||
bits = 64
|
||||
sys_name = platform.system()
|
||||
if 'Linux' in sys_name and (platform.platform().find('arm') > 0 or platform.platform().find('aarch64') > 0):
|
||||
sys_name = 'LinuxARM'
|
||||
if 'CYGWIN_NT' in sys_name:
|
||||
sys_name = 'Windows'
|
||||
if 'MSYS_NT' in sys_name:
|
||||
sys_name = 'Windows'
|
||||
if 'MINGW' in sys_name:
|
||||
sys_name = 'Windows'
|
||||
return arduino_platform_names[sys_name][bits]
|
||||
|
||||
def main():
|
||||
global verbose
|
||||
# Support optional "-q" quiet mode simply
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == "-q":
|
||||
verbose = False
|
||||
# Remove a symlink generated in 2.6.3 which causes later issues since the tarball can't properly overwrite it
|
||||
if (os.path.exists('python3/python3')):
|
||||
os.unlink('python3/python3')
|
||||
print('Platform: {0}'.format(identify_platform()))
|
||||
tools_to_download = load_tools_list('../package/package_pico_index.template.json', identify_platform())
|
||||
mkdir_p(dist_dir)
|
||||
for tool in tools_to_download:
|
||||
get_tool(tool)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Reference in a new issue