mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
Merge branch 'master' into powerPulses
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
FROM ubuntu:rolling
|
FROM ubuntu:rolling
|
||||||
MAINTAINER Ben V. Brown <ralim@ralimtek.com>
|
LABEL maintainer="Ben V. Brown <ralim@ralimtek.com>"
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
# Setup the ARM GCC toolchain
|
# Setup the ARM GCC toolchain
|
||||||
@@ -9,19 +9,13 @@ RUN apt-get update && \
|
|||||||
apt-get upgrade -y && \
|
apt-get upgrade -y && \
|
||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
make \
|
make \
|
||||||
git \
|
|
||||||
bzip2 \
|
bzip2 \
|
||||||
git \
|
|
||||||
golang \
|
|
||||||
python3 \
|
python3 \
|
||||||
wget && \
|
wget && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
wget -qO- https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/RC2.1/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 | tar -xj
|
wget -qO- https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/RC2.1/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 | tar -xj
|
||||||
|
|
||||||
# Add compiler to the path
|
# Add compiler to the path
|
||||||
|
|
||||||
ENV PATH "/build/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH"
|
ENV PATH "/build/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH"
|
||||||
# Get the github release tool
|
|
||||||
RUN go get -u github.com/aktau/github-release
|
|
||||||
COPY . /build/source
|
COPY . /build/source
|
||||||
COPY ./ci /build/ci
|
COPY ./ci /build/ci
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#coding=utf-8
|
# coding=utf-8
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -81,21 +81,23 @@ def escapeC(s):
|
|||||||
|
|
||||||
def getConstants():
|
def getConstants():
|
||||||
# Extra constants that are used in the firmware that are shared across all languages
|
# Extra constants that are used in the firmware that are shared across all languages
|
||||||
consants =[]
|
consants = []
|
||||||
consants.append(('SymbolPlus','+'))
|
consants.append(('SymbolPlus', '+'))
|
||||||
consants.append(('SymbolMinus','-'))
|
consants.append(('SymbolMinus', '-'))
|
||||||
consants.append(('SymbolSpace',' '))
|
consants.append(('SymbolSpace', ' '))
|
||||||
consants.append(('SymbolDot','.'))
|
consants.append(('SymbolDot', '.'))
|
||||||
consants.append(('SymbolDegC','C'))
|
consants.append(('SymbolDegC', 'C'))
|
||||||
consants.append(('SymbolDegF','F'))
|
consants.append(('SymbolDegF', 'F'))
|
||||||
consants.append(('SymbolMinutes','M'))
|
consants.append(('SymbolMinutes', 'M'))
|
||||||
consants.append(('SymbolSeconds','S'))
|
consants.append(('SymbolSeconds', 'S'))
|
||||||
consants.append(('SymbolWatts','W'))
|
consants.append(('SymbolWatts', 'W'))
|
||||||
consants.append(('SymbolVolts','V'))
|
consants.append(('SymbolVolts', 'V'))
|
||||||
consants.append(('SymbolDC','DC'))
|
consants.append(('SymbolDC', 'DC'))
|
||||||
consants.append(('SymbolCellCount','S'))
|
consants.append(('SymbolCellCount', 'S'))
|
||||||
consants.append(('SymbolVersionNumber','V2.06'))
|
consants.append(('SymbolVersionNumber', 'V2.06'))
|
||||||
return consants
|
return consants
|
||||||
|
|
||||||
|
|
||||||
def getTipModelEnumTS80():
|
def getTipModelEnumTS80():
|
||||||
constants = []
|
constants = []
|
||||||
constants.append("B02")
|
constants.append("B02")
|
||||||
@@ -104,18 +106,20 @@ def getTipModelEnumTS80():
|
|||||||
constants.append("User") # User
|
constants.append("User") # User
|
||||||
return constants
|
return constants
|
||||||
|
|
||||||
|
|
||||||
def getTipModelEnumTS100():
|
def getTipModelEnumTS100():
|
||||||
constants = []
|
constants = []
|
||||||
constants.append("B02")
|
constants.append("B02")
|
||||||
constants.append("D24")
|
constants.append("D24")
|
||||||
constants.append("BC2")
|
constants.append("BC2")
|
||||||
constants.append(" C1")
|
constants.append(" C1")
|
||||||
constants.append("TS100")# end of miniware
|
constants.append("TS100") # end of miniware
|
||||||
constants.append("BC2")
|
constants.append("BC2")
|
||||||
constants.append("Hakko")# end of hakko
|
constants.append("Hakko") # end of hakko
|
||||||
constants.append("User")
|
constants.append("User")
|
||||||
return constants
|
return constants
|
||||||
|
|
||||||
|
|
||||||
def getDebugMenu():
|
def getDebugMenu():
|
||||||
constants = []
|
constants = []
|
||||||
constants.append(datetime.today().strftime('%d-%m-%y'))
|
constants.append(datetime.today().strftime('%d-%m-%y'))
|
||||||
@@ -134,7 +138,7 @@ def getDebugMenu():
|
|||||||
|
|
||||||
def getLetterCounts(defs, lang):
|
def getLetterCounts(defs, lang):
|
||||||
textList = []
|
textList = []
|
||||||
#iterate over all strings
|
# iterate over all strings
|
||||||
obj = lang['menuOptions']
|
obj = lang['menuOptions']
|
||||||
for mod in defs['menuOptions']:
|
for mod in defs['menuOptions']:
|
||||||
eid = mod['id']
|
eid = mod['id']
|
||||||
@@ -187,26 +191,25 @@ def getLetterCounts(defs, lang):
|
|||||||
line = line.replace('\n', '').replace('\r', '')
|
line = line.replace('\n', '').replace('\r', '')
|
||||||
line = line.replace('\\n', '').replace('\\r', '')
|
line = line.replace('\\n', '').replace('\\r', '')
|
||||||
if len(line):
|
if len(line):
|
||||||
#print(line)
|
# print(line)
|
||||||
for letter in line:
|
for letter in line:
|
||||||
symbolCounts[letter] = symbolCounts.get(letter, 0) + 1
|
symbolCounts[letter] = symbolCounts.get(letter, 0) + 1
|
||||||
symbolCounts = sorted(
|
symbolCounts = sorted(
|
||||||
symbolCounts.items(),
|
symbolCounts.items(),
|
||||||
key=lambda kv: (kv[1],kv[0])) # swap to Big -> little sort order
|
key=lambda kv: (kv[1], kv[0])) # swap to Big -> little sort order
|
||||||
symbolCounts = list(map(lambda x: x[0], symbolCounts))
|
symbolCounts = list(map(lambda x: x[0], symbolCounts))
|
||||||
symbolCounts.reverse()
|
symbolCounts.reverse()
|
||||||
return symbolCounts
|
return symbolCounts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getFontMapAndTable(textList):
|
def getFontMapAndTable(textList):
|
||||||
# the text list is sorted
|
# the text list is sorted
|
||||||
# allocate out these in their order as number codes
|
# allocate out these in their order as number codes
|
||||||
symbolMap = {}
|
symbolMap = {}
|
||||||
symbolMap['\n'] = '\\x01'
|
symbolMap['\n'] = '\\x01' # Force insert the newline char
|
||||||
index = 2 # start at 2, as 0= null terminator,1 = new line
|
index = 2 # start at 2, as 0= null terminator,1 = new line
|
||||||
forcedFirstSymbols = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
forcedFirstSymbols = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||||||
#enforce numbers are first
|
# enforce numbers are first
|
||||||
for sym in forcedFirstSymbols:
|
for sym in forcedFirstSymbols:
|
||||||
symbolMap[sym] = "\\x%0.2X" % index
|
symbolMap[sym] = "\\x%0.2X" % index
|
||||||
index = index + 1
|
index = index + 1
|
||||||
@@ -229,12 +232,14 @@ def getFontMapAndTable(textList):
|
|||||||
print('Missing Large font element for {}'.format(sym))
|
print('Missing Large font element for {}'.format(sym))
|
||||||
exit(1)
|
exit(1)
|
||||||
fontLine = fontTable[sym]
|
fontLine = fontTable[sym]
|
||||||
fontTableStrings.append(fontLine + "//{} -> {}".format(symbolMap[sym],sym))
|
fontTableStrings.append(
|
||||||
|
fontLine + "//{} -> {}".format(symbolMap[sym], sym))
|
||||||
if sym not in fontSmallTable:
|
if sym not in fontSmallTable:
|
||||||
print('Missing Small font element for {}'.format(sym))
|
print('Missing Small font element for {}'.format(sym))
|
||||||
exit(1)
|
exit(1)
|
||||||
fontLine = fontSmallTable[sym]
|
fontLine = fontSmallTable[sym]
|
||||||
fontSmallTableStrings.append(fontLine + "//{} -> {}".format(symbolMap[sym],sym))
|
fontSmallTableStrings.append(
|
||||||
|
fontLine + "//{} -> {}".format(symbolMap[sym], sym))
|
||||||
|
|
||||||
for sym in textList:
|
for sym in textList:
|
||||||
if sym not in fontTable:
|
if sym not in fontTable:
|
||||||
@@ -242,12 +247,14 @@ def getFontMapAndTable(textList):
|
|||||||
exit(1)
|
exit(1)
|
||||||
if sym not in forcedFirstSymbols:
|
if sym not in forcedFirstSymbols:
|
||||||
fontLine = fontTable[sym]
|
fontLine = fontTable[sym]
|
||||||
fontTableStrings.append(fontLine + "//{} -> {}".format(symbolMap[sym],sym))
|
fontTableStrings.append(
|
||||||
|
fontLine + "//{} -> {}".format(symbolMap[sym], sym))
|
||||||
if sym not in fontSmallTable:
|
if sym not in fontSmallTable:
|
||||||
print('Missing Small font element for {}'.format(sym))
|
print('Missing Small font element for {}'.format(sym))
|
||||||
exit(1)
|
exit(1)
|
||||||
fontLine = fontSmallTable[sym]
|
fontLine = fontSmallTable[sym]
|
||||||
fontSmallTableStrings.append(fontLine + "//{} -> {}".format(symbolMap[sym],sym))
|
fontSmallTableStrings.append(
|
||||||
|
fontLine + "//{} -> {}".format(symbolMap[sym], sym))
|
||||||
outputTable = "const uint8_t USER_FONT_12[] = {" + to_unicode("\n")
|
outputTable = "const uint8_t USER_FONT_12[] = {" + to_unicode("\n")
|
||||||
for line in fontTableStrings:
|
for line in fontTableStrings:
|
||||||
# join font table int one large string
|
# join font table int one large string
|
||||||
@@ -265,7 +272,7 @@ def getFontMapAndTable(textList):
|
|||||||
def convStr(symbolConversionTable, text):
|
def convStr(symbolConversionTable, text):
|
||||||
# convert all of the symbols from the string into escapes for their content
|
# convert all of the symbols from the string into escapes for their content
|
||||||
outputString = ""
|
outputString = ""
|
||||||
for c in text.replace('\\r', '').replace('\\n','\n'):
|
for c in text.replace('\\r', '').replace('\\n', '\n'):
|
||||||
if c not in symbolConversionTable:
|
if c not in symbolConversionTable:
|
||||||
print('Missing font definition for {}'.format(c))
|
print('Missing font definition for {}'.format(c))
|
||||||
else:
|
else:
|
||||||
@@ -276,7 +283,7 @@ def convStr(symbolConversionTable, text):
|
|||||||
def writeLanguage(languageCode, defs, f):
|
def writeLanguage(languageCode, defs, f):
|
||||||
print("Generating block for " + languageCode)
|
print("Generating block for " + languageCode)
|
||||||
lang = langDict[languageCode]
|
lang = langDict[languageCode]
|
||||||
#Iterate over all of the text to build up the symbols & counts
|
# Iterate over all of the text to build up the symbols & counts
|
||||||
textList = getLetterCounts(defs, lang)
|
textList = getLetterCounts(defs, lang)
|
||||||
# From the letter counts, need to make a symbol translator & write out the font
|
# From the letter counts, need to make a symbol translator & write out the font
|
||||||
(fontTableText, symbolConversionTable) = getFontMapAndTable(textList)
|
(fontTableText, symbolConversionTable) = getFontMapAndTable(textList)
|
||||||
@@ -290,7 +297,6 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
|
|
||||||
f.write(to_unicode("// ---- " + langName + " ----\n\n"))
|
f.write(to_unicode("// ---- " + langName + " ----\n\n"))
|
||||||
|
|
||||||
|
|
||||||
# ----- Writing SettingsDescriptions
|
# ----- Writing SettingsDescriptions
|
||||||
obj = lang['menuOptions']
|
obj = lang['menuOptions']
|
||||||
f.write(to_unicode("const char* SettingsDescriptions[] = {\n"))
|
f.write(to_unicode("const char* SettingsDescriptions[] = {\n"))
|
||||||
@@ -316,14 +322,15 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
|
|
||||||
for mod in defs['messages']:
|
for mod in defs['messages']:
|
||||||
eid = mod['id']
|
eid = mod['id']
|
||||||
if eid not in obj:
|
sourceText = ""
|
||||||
|
if 'default' in mod:
|
||||||
|
sourceText = (mod['default'])
|
||||||
|
if eid in obj:
|
||||||
|
sourceText = (obj[eid])
|
||||||
|
translatedText = convStr(symbolConversionTable, sourceText)
|
||||||
f.write(
|
f.write(
|
||||||
to_unicode("const char* " + eid + " = \"" +
|
to_unicode("const char* " + eid + " = \"" +
|
||||||
convStr(symbolConversionTable, (mod['default'])) + "\";"+ "//{} \n".format(mod['default'])))
|
translatedText + "\";" + "//{} \n".format(sourceText.replace('\n', '_'))))
|
||||||
else:
|
|
||||||
f.write(
|
|
||||||
to_unicode("const char* " + eid + " = \"" +
|
|
||||||
convStr(symbolConversionTable, (obj[eid])) + "\";"+ "//{} \n".format(obj[eid])))
|
|
||||||
|
|
||||||
f.write(to_unicode("\n"))
|
f.write(to_unicode("\n"))
|
||||||
|
|
||||||
@@ -335,7 +342,7 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
eid = mod['id']
|
eid = mod['id']
|
||||||
f.write(
|
f.write(
|
||||||
to_unicode("const char* " + eid + " = \"" +
|
to_unicode("const char* " + eid + " = \"" +
|
||||||
convStr(symbolConversionTable, obj[eid]) + "\";"+ "//{} \n".format(obj[eid])))
|
convStr(symbolConversionTable, obj[eid]) + "\";" + "//{} \n".format(obj[eid])))
|
||||||
|
|
||||||
f.write(to_unicode("\n"))
|
f.write(to_unicode("\n"))
|
||||||
|
|
||||||
@@ -344,7 +351,7 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
for x in constants:
|
for x in constants:
|
||||||
f.write(
|
f.write(
|
||||||
to_unicode("const char* " + x[0] + " = \"" +
|
to_unicode("const char* " + x[0] + " = \"" +
|
||||||
convStr(symbolConversionTable, x[1]) + "\";"+ "//{} \n".format(x[1])))
|
convStr(symbolConversionTable, x[1]) + "\";" + "//{} \n".format(x[1])))
|
||||||
|
|
||||||
f.write(to_unicode("\n"))
|
f.write(to_unicode("\n"))
|
||||||
# Write out tip model strings
|
# Write out tip model strings
|
||||||
@@ -352,10 +359,12 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
f.write(to_unicode("const char* TipModelStrings[] = {\n"))
|
f.write(to_unicode("const char* TipModelStrings[] = {\n"))
|
||||||
f.write(to_unicode("#ifdef MODEL_TS100\n"))
|
f.write(to_unicode("#ifdef MODEL_TS100\n"))
|
||||||
for c in getTipModelEnumTS100():
|
for c in getTipModelEnumTS100():
|
||||||
f.write(to_unicode("\t \"" + convStr(symbolConversionTable, c) + "\","+ "//{} \n".format(c)))
|
f.write(to_unicode("\t \"" + convStr(symbolConversionTable,
|
||||||
|
c) + "\"," + "//{} \n".format(c)))
|
||||||
f.write(to_unicode("#else\n"))
|
f.write(to_unicode("#else\n"))
|
||||||
for c in getTipModelEnumTS80():
|
for c in getTipModelEnumTS80():
|
||||||
f.write(to_unicode("\t \"" + convStr(symbolConversionTable, c) + "\","+ "//{} \n".format(c)))
|
f.write(to_unicode("\t \"" + convStr(symbolConversionTable,
|
||||||
|
c) + "\"," + "//{} \n".format(c)))
|
||||||
f.write(to_unicode("#endif\n"))
|
f.write(to_unicode("#endif\n"))
|
||||||
|
|
||||||
f.write(to_unicode("};\n\n"))
|
f.write(to_unicode("};\n\n"))
|
||||||
@@ -364,7 +373,8 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
f.write(to_unicode("const char* DebugMenu[] = {\n"))
|
f.write(to_unicode("const char* DebugMenu[] = {\n"))
|
||||||
|
|
||||||
for c in getDebugMenu():
|
for c in getDebugMenu():
|
||||||
f.write(to_unicode("\t \"" + convStr(symbolConversionTable, c) + "\","+ "//{} \n".format(c)))
|
f.write(to_unicode("\t \"" + convStr(symbolConversionTable,
|
||||||
|
c) + "\"," + "//{} \n".format(c)))
|
||||||
f.write(to_unicode("};\n\n"))
|
f.write(to_unicode("};\n\n"))
|
||||||
|
|
||||||
# ----- Menu Options
|
# ----- Menu Options
|
||||||
@@ -392,12 +402,12 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
convStr(symbolConversionTable, (obj[eid]['text2'][0])) +
|
convStr(symbolConversionTable, (obj[eid]['text2'][0])) +
|
||||||
"\", \"" +
|
"\", \"" +
|
||||||
convStr(symbolConversionTable, (obj[eid]['text2'][1])) +
|
convStr(symbolConversionTable, (obj[eid]['text2'][1])) +
|
||||||
"\" },"+ "//{} \n".format(obj[eid]['text2'])))
|
"\" }," + "//{} \n".format(obj[eid]['text2'])))
|
||||||
else:
|
else:
|
||||||
f.write(
|
f.write(
|
||||||
to_unicode("{ \"" +
|
to_unicode("{ \"" +
|
||||||
convStr(symbolConversionTable, (obj[eid]['text'])) +
|
convStr(symbolConversionTable, (obj[eid]['text'])) +
|
||||||
"\" },"+ "//{} \n".format(obj[eid]['text'])))
|
"\" }," + "//{} \n".format(obj[eid]['text'])))
|
||||||
if 'feature' in mod:
|
if 'feature' in mod:
|
||||||
f.write(to_unicode("#endif\n"))
|
f.write(to_unicode("#endif\n"))
|
||||||
|
|
||||||
@@ -416,7 +426,7 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
f.write(
|
f.write(
|
||||||
to_unicode("\"" +
|
to_unicode("\"" +
|
||||||
convStr(symbolConversionTable, (obj[eid]['text2'][0]) +
|
convStr(symbolConversionTable, (obj[eid]['text2'][0]) +
|
||||||
"\\n" + obj[eid]['text2'][1]) + "\","+ "//{} \n".format(obj[eid]['text2'])))
|
"\\n" + obj[eid]['text2'][1]) + "\"," + "//{} \n".format(obj[eid]['text2'])))
|
||||||
|
|
||||||
f.write(to_unicode("};\n\n"))
|
f.write(to_unicode("};\n\n"))
|
||||||
|
|
||||||
@@ -433,7 +443,7 @@ def writeLanguage(languageCode, defs, f):
|
|||||||
f.write(
|
f.write(
|
||||||
to_unicode("\"" +
|
to_unicode("\"" +
|
||||||
convStr(symbolConversionTable, (obj[eid]['desc'])) +
|
convStr(symbolConversionTable, (obj[eid]['desc'])) +
|
||||||
"\","+ "//{} \n".format(obj[eid]['desc'])))
|
"\"," + "//{} \n".format(obj[eid]['desc'])))
|
||||||
|
|
||||||
f.write(to_unicode("};\n\n"))
|
f.write(to_unicode("};\n\n"))
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,9 @@
|
|||||||
"TipDisconnectedString": "TIP DISCONNECTED",
|
"TipDisconnectedString": "TIP DISCONNECTED",
|
||||||
"SolderingAdvancedPowerPrompt": "Power: ",
|
"SolderingAdvancedPowerPrompt": "Power: ",
|
||||||
"OffString": "Off",
|
"OffString": "Off",
|
||||||
"ResetOKMessage":"Reset OK",
|
"ResetOKMessage": "Reset OK",
|
||||||
"YourGainMessage":"Your Gain:"
|
"YourGainMessage": "Your Gain:",
|
||||||
|
"SettingsResetMessage": "Settings were\nreset!"
|
||||||
},
|
},
|
||||||
"characters": {
|
"characters": {
|
||||||
"SettingRightChar": "R",
|
"SettingRightChar": "R",
|
||||||
|
|||||||
@@ -88,7 +88,12 @@ var def =
|
|||||||
{
|
{
|
||||||
"id": "YourGainMessage",
|
"id": "YourGainMessage",
|
||||||
"maxLen": 8,
|
"maxLen": 8,
|
||||||
"default":"Your Gain"
|
"default": "Your Gain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SettingsResetMessage",
|
||||||
|
"maxLen": 16,
|
||||||
|
"default": "Settings were\nreset!"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"characters": [
|
"characters": [
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<project>
|
|
||||||
<configuration id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.980996604" name="Release">
|
|
||||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
|
|
||||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-348041022799175818" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
|
||||||
</provider>
|
|
||||||
</extension>
|
|
||||||
</configuration>
|
|
||||||
</project>
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
#define SETTINGS_H_
|
#define SETTINGS_H_
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "stm32f1xx_hal.h"
|
#include "stm32f1xx_hal.h"
|
||||||
#define SETTINGSVERSION ( 0x1A )
|
#define SETTINGSVERSION ( 0x1B )
|
||||||
/*Change this if you change the struct below to prevent people getting \
|
/*Change this if you change the struct below to prevent people getting \
|
||||||
out of sync*/
|
out of sync*/
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ typedef struct {
|
|||||||
extern volatile systemSettingsType systemSettings;
|
extern volatile systemSettingsType systemSettings;
|
||||||
|
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
void restoreSettings();
|
bool restoreSettings();
|
||||||
uint8_t lookupVoltageLevel(uint8_t level);
|
uint8_t lookupVoltageLevel(uint8_t level);
|
||||||
void resetSettings();
|
void resetSettings();
|
||||||
bool showBootLogoIfavailable();
|
bool showBootLogoIfavailable();
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ extern const char* SolderingAdvancedPowerPrompt;
|
|||||||
extern const char* OffString;
|
extern const char* OffString;
|
||||||
extern const char* ResetOKMessage;
|
extern const char* ResetOKMessage;
|
||||||
extern const char* YourGainMessage;
|
extern const char* YourGainMessage;
|
||||||
|
extern const char* SettingsResetMessage;
|
||||||
|
|
||||||
extern const char* SettingTrueChar;
|
extern const char* SettingTrueChar;
|
||||||
extern const char* SettingFalseChar;
|
extern const char* SettingFalseChar;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "Setup.h"
|
#include "Setup.h"
|
||||||
extern uint8_t PCBVersion;
|
extern uint8_t PCBVersion;
|
||||||
extern uint32_t currentTempTargetDegC;
|
extern uint32_t currentTempTargetDegC;
|
||||||
|
extern bool settingsWereReset;
|
||||||
enum ButtonState {
|
enum ButtonState {
|
||||||
BUTTON_NONE = 0, /* No buttons pressed / < filter time*/
|
BUTTON_NONE = 0, /* No buttons pressed / < filter time*/
|
||||||
BUTTON_F_SHORT = 1, /* User has pressed the front button*/
|
BUTTON_F_SHORT = 1, /* User has pressed the front button*/
|
||||||
@@ -14,7 +15,7 @@ enum ButtonState {
|
|||||||
BUTTON_B_LONG = 8, /* User is holding the back button*/
|
BUTTON_B_LONG = 8, /* User is holding the back button*/
|
||||||
BUTTON_BOTH = 16, /* User has pressed both buttons*/
|
BUTTON_BOTH = 16, /* User has pressed both buttons*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note:
|
* Note:
|
||||||
* Pressed means press + release, we trigger on a full \__/ pulse
|
* Pressed means press + release, we trigger on a full \__/ pulse
|
||||||
* holding means it has gone low, and been low for longer than filter time
|
* holding means it has gone low, and been low for longer than filter time
|
||||||
|
|||||||
@@ -504,7 +504,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) {
|
|||||||
OLED::print(SolderingAdvancedPowerPrompt); // Power:
|
OLED::print(SolderingAdvancedPowerPrompt); // Power:
|
||||||
OLED::printNumber(x10WattHistory.average() / 10, 2);
|
OLED::printNumber(x10WattHistory.average() / 10, 2);
|
||||||
OLED::print(SymbolDot);
|
OLED::print(SymbolDot);
|
||||||
OLED::printNumber(x10WattHistory.average()% 10, 1);
|
OLED::printNumber(x10WattHistory.average() % 10, 1);
|
||||||
OLED::print(SymbolWatts);
|
OLED::print(SymbolWatts);
|
||||||
|
|
||||||
if (systemSettings.sensitivity && systemSettings.SleepTime) {
|
if (systemSettings.sensitivity && systemSettings.SleepTime) {
|
||||||
@@ -702,6 +702,17 @@ void startGUITask(void const *argument __unused) {
|
|||||||
ticks = xTaskGetTickCount(); // make timeout now so we will exit
|
ticks = xTaskGetTickCount(); // make timeout now so we will exit
|
||||||
GUIDelay();
|
GUIDelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsWereReset) {
|
||||||
|
//Display alert settings were reset
|
||||||
|
OLED::setFont(1);
|
||||||
|
OLED::setCursor(0, 0);
|
||||||
|
OLED::print(SettingsResetMessage);
|
||||||
|
OLED::refresh();
|
||||||
|
waitForButtonPressOrTimeout(1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (systemSettings.autoStartMode) {
|
if (systemSettings.autoStartMode) {
|
||||||
// jump directly to the autostart mode
|
// jump directly to the autostart mode
|
||||||
if (systemSettings.autoStartMode == 1)
|
if (systemSettings.autoStartMode == 1)
|
||||||
@@ -756,7 +767,6 @@ void startGUITask(void const *argument __unused) {
|
|||||||
break;
|
break;
|
||||||
case BUTTON_B_SHORT:
|
case BUTTON_B_SHORT:
|
||||||
enterSettingsMenu(); // enter the settings menu
|
enterSettingsMenu(); // enter the settings menu
|
||||||
saveSettings();
|
|
||||||
buttonLockout = true;
|
buttonLockout = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -155,7 +155,17 @@ void OLED::setFont(uint8_t fontNumber) {
|
|||||||
fontWidth = 12;
|
fontWidth = 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline void stripLeaderZeros(char *buffer) {
|
||||||
|
//Removing the leading zero's by swapping them to SymbolSpace
|
||||||
|
// Stop 1 short so that we dont blank entire number if its zero
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if (buffer[i] == 2) {
|
||||||
|
buffer[i] = SymbolSpace[0];
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// maximum places is 5
|
// maximum places is 5
|
||||||
void OLED::printNumber(uint16_t number, uint8_t places) {
|
void OLED::printNumber(uint16_t number, uint8_t places) {
|
||||||
char buffer[7] = { 0 };
|
char buffer[7] = { 0 };
|
||||||
@@ -185,14 +195,7 @@ void OLED::printNumber(uint16_t number, uint8_t places) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = 2 + number % 10;
|
buffer[0] = 2 + number % 10;
|
||||||
//Removing the leading zero's by swapping them to SymbolSpace
|
stripLeaderZeros(buffer);
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
if (buffer[i] == 2) {
|
|
||||||
buffer[i] = SymbolSpace[0];
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print(buffer);
|
print(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ void saveSettings() {
|
|||||||
pEraseInit.PageAddress = FLASH_ADDR;
|
pEraseInit.PageAddress = FLASH_ADDR;
|
||||||
uint32_t failingAddress = 0;
|
uint32_t failingAddress = 0;
|
||||||
HAL_IWDG_Refresh(&hiwdg);
|
HAL_IWDG_Refresh(&hiwdg);
|
||||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR |
|
__HAL_FLASH_CLEAR_FLAG(
|
||||||
FLASH_FLAG_BSY);
|
FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_BSY);
|
||||||
HAL_FLASH_Unlock();
|
HAL_FLASH_Unlock();
|
||||||
HAL_Delay(10);
|
HAL_Delay(10);
|
||||||
HAL_IWDG_Refresh(&hiwdg);
|
HAL_IWDG_Refresh(&hiwdg);
|
||||||
@@ -34,7 +34,7 @@ void saveSettings() {
|
|||||||
//^ Erase the page of flash (1024 bytes on this stm32)
|
//^ Erase the page of flash (1024 bytes on this stm32)
|
||||||
// erased the chunk
|
// erased the chunk
|
||||||
// now we program it
|
// now we program it
|
||||||
uint16_t *data = (uint16_t *)&systemSettings;
|
uint16_t *data = (uint16_t*) &systemSettings;
|
||||||
HAL_FLASH_Unlock();
|
HAL_FLASH_Unlock();
|
||||||
|
|
||||||
for (uint8_t i = 0; i < (sizeof(systemSettingsType) / 2); i++) {
|
for (uint8_t i = 0; i < (sizeof(systemSettingsType) / 2); i++) {
|
||||||
@@ -45,11 +45,11 @@ void saveSettings() {
|
|||||||
HAL_FLASH_Lock();
|
HAL_FLASH_Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreSettings() {
|
bool restoreSettings() {
|
||||||
// We read the flash
|
// We read the flash
|
||||||
uint16_t *data = (uint16_t *)&systemSettings;
|
uint16_t *data = (uint16_t*) &systemSettings;
|
||||||
for (uint8_t i = 0; i < (sizeof(systemSettingsType) / 2); i++) {
|
for (uint8_t i = 0; i < (sizeof(systemSettingsType) / 2); i++) {
|
||||||
data[i] = *((uint16_t *)(FLASH_ADDR + (i * 2)));
|
data[i] = *((uint16_t*) (FLASH_ADDR + (i * 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the version is correct were done
|
// if the version is correct were done
|
||||||
@@ -57,7 +57,9 @@ void restoreSettings() {
|
|||||||
if (systemSettings.version != SETTINGSVERSION) {
|
if (systemSettings.version != SETTINGSVERSION) {
|
||||||
// probably not setup
|
// probably not setup
|
||||||
resetSettings();
|
resetSettings();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// Lookup function for cutoff setting -> X10 voltage
|
// Lookup function for cutoff setting -> X10 voltage
|
||||||
/*
|
/*
|
||||||
@@ -74,9 +76,8 @@ uint8_t lookupVoltageLevel(uint8_t level) {
|
|||||||
return (level * 33) + (33 * 2);
|
return (level * 33) + (33 * 2);
|
||||||
}
|
}
|
||||||
void resetSettings() {
|
void resetSettings() {
|
||||||
memset((void *)&systemSettings, 0, sizeof(systemSettingsType));
|
memset((void*) &systemSettings, 0, sizeof(systemSettingsType));
|
||||||
systemSettings.SleepTemp =
|
systemSettings.SleepTemp = 150; // Temperature the iron sleeps at - default 150.0 C
|
||||||
150; // Temperature the iron sleeps at - default 150.0 C
|
|
||||||
systemSettings.SleepTime = 6; // How many seconds/minutes we wait until going
|
systemSettings.SleepTime = 6; // How many seconds/minutes we wait until going
|
||||||
// to sleep - default 1 min
|
// to sleep - default 1 min
|
||||||
systemSettings.SolderingTemp = 320; // Default soldering temp is 320.0 C
|
systemSettings.SolderingTemp = 320; // Default soldering temp is 320.0 C
|
||||||
@@ -84,8 +85,7 @@ void resetSettings() {
|
|||||||
systemSettings.version =
|
systemSettings.version =
|
||||||
SETTINGSVERSION; // Store the version number to allow for easier upgrades
|
SETTINGSVERSION; // Store the version number to allow for easier upgrades
|
||||||
systemSettings.detailedSoldering = 0; // Detailed soldering screen
|
systemSettings.detailedSoldering = 0; // Detailed soldering screen
|
||||||
systemSettings.detailedIDLE =
|
systemSettings.detailedIDLE = 0; // Detailed idle screen (off for first time users)
|
||||||
0; // Detailed idle screen (off for first time users)
|
|
||||||
systemSettings.OrientationMode = 2; // Default to automatic
|
systemSettings.OrientationMode = 2; // Default to automatic
|
||||||
systemSettings.sensitivity = 7; // Default high sensitivity
|
systemSettings.sensitivity = 7; // Default high sensitivity
|
||||||
#ifdef MODEL_TS80
|
#ifdef MODEL_TS80
|
||||||
@@ -94,26 +94,23 @@ void resetSettings() {
|
|||||||
#else
|
#else
|
||||||
systemSettings.voltageDiv = 467; // Default divider from schematic
|
systemSettings.voltageDiv = 467; // Default divider from schematic
|
||||||
#endif
|
#endif
|
||||||
systemSettings.ShutdownTime =
|
systemSettings.ShutdownTime = 10; // How many minutes until the unit turns itself off
|
||||||
10; // How many minutes until the unit turns itself off
|
systemSettings.boostModeEnabled = 1; // Default to having boost mode on as most people prefer it
|
||||||
systemSettings.boostModeEnabled =
|
|
||||||
1; // Default to having boost mode on as most people prefer it
|
|
||||||
systemSettings.BoostTemp = 420; // default to 400C
|
systemSettings.BoostTemp = 420; // default to 400C
|
||||||
systemSettings.autoStartMode = 0; // Auto start off for safety
|
systemSettings.autoStartMode = 0; // Auto start off for safety
|
||||||
systemSettings.coolingTempBlink =
|
systemSettings.coolingTempBlink = 0; // Blink the temperature on the cooling screen when its > 50C
|
||||||
0; // Blink the temperature on the cooling screen when its > 50C
|
|
||||||
systemSettings.temperatureInF = 0; // default to 0
|
systemSettings.temperatureInF = 0; // default to 0
|
||||||
systemSettings.descriptionScrollSpeed = 0; // default to slow
|
systemSettings.descriptionScrollSpeed = 0; // default to slow
|
||||||
|
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
systemSettings.CalibrationOffset = 850; // the adc offset in uV
|
systemSettings.CalibrationOffset = 900; // the adc offset in uV
|
||||||
systemSettings.pidPowerLimit=70; // Sets the max pwm power limit
|
systemSettings.pidPowerLimit=70; // Sets the max pwm power limit
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef MODEL_TS80
|
#ifdef MODEL_TS80
|
||||||
systemSettings.pidPowerLimit=24; // Sets the max pwm power limit
|
systemSettings.pidPowerLimit = 24; // Sets the max pwm power limit
|
||||||
|
|
||||||
systemSettings.CalibrationOffset = 300; // the adc offset in uV
|
systemSettings.CalibrationOffset = 900; // the adc offset in uV
|
||||||
#endif
|
#endif
|
||||||
saveSettings(); // Save defaults
|
saveSettings(); // Save defaults
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
|||||||
#include "TipThermoModel.h"
|
#include "TipThermoModel.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
extern uint32_t lastButtonTime;
|
extern uint32_t lastButtonTime;
|
||||||
void gui_Menu(const menuitem* menu);
|
void gui_Menu(const menuitem *menu);
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
static void settings_setInputVRange(void);
|
static void settings_setInputVRange(void);
|
||||||
static void settings_displayInputVRange(void);
|
static void settings_displayInputVRange(void);
|
||||||
@@ -105,9 +105,8 @@ const menuitem rootSettingsMenu[] {
|
|||||||
* Exit
|
* Exit
|
||||||
*/
|
*/
|
||||||
#ifdef MODEL_TS100
|
#ifdef MODEL_TS100
|
||||||
{ (const char*)SettingsDescriptions[0],
|
{ (const char*) SettingsDescriptions[0], { settings_setInputVRange }, {
|
||||||
{ settings_setInputVRange},
|
settings_displayInputVRange } }, /*Voltage input*/
|
||||||
{ settings_displayInputVRange}}, /*Voltage input*/
|
|
||||||
#else
|
#else
|
||||||
{ (const char*) SettingsDescriptions[20], { settings_setInputPRange }, {
|
{ (const char*) SettingsDescriptions[20], { settings_setInputPRange }, {
|
||||||
settings_displayInputPRange } }, /*Voltage input*/
|
settings_displayInputPRange } }, /*Voltage input*/
|
||||||
@@ -231,7 +230,7 @@ static void printShortDescription(uint32_t shortDescIndex,
|
|||||||
OLED::setCharCursor(cursorCharPosition, 0);
|
OLED::setCharCursor(cursorCharPosition, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int userConfirmation(const char* message) {
|
static int userConfirmation(const char *message) {
|
||||||
uint16_t messageWidth = FONT_12_WIDTH * (strlen(message) + 7);
|
uint16_t messageWidth = FONT_12_WIDTH * (strlen(message) + 7);
|
||||||
uint32_t messageStart = xTaskGetTickCount();
|
uint32_t messageStart = xTaskGetTickCount();
|
||||||
|
|
||||||
@@ -697,7 +696,7 @@ static void settings_enterAdvancedMenu(void) {
|
|||||||
gui_Menu(advancedMenu);
|
gui_Menu(advancedMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gui_Menu(const menuitem* menu) {
|
void gui_Menu(const menuitem *menu) {
|
||||||
// Draw the settings menu and provide iteration support etc
|
// Draw the settings menu and provide iteration support etc
|
||||||
uint8_t currentScreen = 0;
|
uint8_t currentScreen = 0;
|
||||||
uint32_t autoRepeatTimer = 0;
|
uint32_t autoRepeatTimer = 0;
|
||||||
@@ -731,11 +730,8 @@ void gui_Menu(const menuitem* menu) {
|
|||||||
/ (systemSettings.descriptionScrollSpeed == 1 ?
|
/ (systemSettings.descriptionScrollSpeed == 1 ?
|
||||||
1 : 2));
|
1 : 2));
|
||||||
descriptionOffset %= descriptionWidth; // Roll around at the end
|
descriptionOffset %= descriptionWidth; // Roll around at the end
|
||||||
|
|
||||||
if (lastOffset != descriptionOffset) {
|
if (lastOffset != descriptionOffset) {
|
||||||
OLED::clearScreen();
|
OLED::clearScreen();
|
||||||
|
|
||||||
//^ Rolling offset based on time
|
|
||||||
OLED::setCursor((OLED_WIDTH - descriptionOffset), 0);
|
OLED::setCursor((OLED_WIDTH - descriptionOffset), 0);
|
||||||
OLED::print(menu[currentScreen].description);
|
OLED::print(menu[currentScreen].description);
|
||||||
lastOffset = descriptionOffset;
|
lastOffset = descriptionOffset;
|
||||||
@@ -807,6 +803,12 @@ void gui_Menu(const menuitem* menu) {
|
|||||||
osDelay(40);
|
osDelay(40);
|
||||||
lcdRefresh = false;
|
lcdRefresh = false;
|
||||||
}
|
}
|
||||||
|
if ((xTaskGetTickCount() - lastButtonTime) > (1000 * 30)) {
|
||||||
|
// If user has not pressed any buttons in 30 seconds, exit back a menu layer
|
||||||
|
// This will trickle the user back to the main screen eventually
|
||||||
|
earlyExit = true;
|
||||||
|
descriptionStart = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ uint8_t PCBVersion = 0;
|
|||||||
uint32_t currentTempTargetDegC = 0; // Current temperature target in C
|
uint32_t currentTempTargetDegC = 0; // Current temperature target in C
|
||||||
uint32_t lastMovementTime = 0;
|
uint32_t lastMovementTime = 0;
|
||||||
int16_t idealQCVoltage = 0;
|
int16_t idealQCVoltage = 0;
|
||||||
|
bool settingsWereReset = false;
|
||||||
// FreeRTOS variables
|
// FreeRTOS variables
|
||||||
|
|
||||||
osThreadId GUITaskHandle;
|
osThreadId GUITaskHandle;
|
||||||
@@ -74,7 +75,7 @@ int main(void) {
|
|||||||
systemSettings.sensitivity = 0;
|
systemSettings.sensitivity = 0;
|
||||||
}
|
}
|
||||||
HAL_IWDG_Refresh(&hiwdg);
|
HAL_IWDG_Refresh(&hiwdg);
|
||||||
restoreSettings(); // load the settings from flash
|
settingsWereReset = restoreSettings(); // load the settings from flash
|
||||||
|
|
||||||
HAL_IWDG_Refresh(&hiwdg);
|
HAL_IWDG_Refresh(&hiwdg);
|
||||||
|
|
||||||
@@ -291,7 +292,7 @@ bool showBootLogoIfavailable() {
|
|||||||
uint16_t temp[98];
|
uint16_t temp[98];
|
||||||
|
|
||||||
for (uint8_t i = 0; i < (98); i++) {
|
for (uint8_t i = 0; i < (98); i++) {
|
||||||
temp[i] = *(uint16_t *) (FLASH_LOGOADDR + (i * 2));
|
temp[i] = *(uint16_t*) (FLASH_LOGOADDR + (i * 2));
|
||||||
}
|
}
|
||||||
uint8_t temp8[98 * 2];
|
uint8_t temp8[98 * 2];
|
||||||
for (uint8_t i = 0; i < 98; i++) {
|
for (uint8_t i = 0; i < 98; i++) {
|
||||||
@@ -308,7 +309,7 @@ bool showBootLogoIfavailable() {
|
|||||||
if (temp8[3] != 0x0D)
|
if (temp8[3] != 0x0D)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
OLED::drawArea(0, 0, 96, 16, (uint8_t *) (temp8 + 4));
|
OLED::drawArea(0, 0, 96, 16, (uint8_t*) (temp8 + 4));
|
||||||
OLED::refresh();
|
OLED::refresh();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,11 @@ then
|
|||||||
echo "Building firmware for $model in $lang"
|
echo "Building firmware for $model in $lang"
|
||||||
make -j lang="$lang" model="$model" >/dev/null
|
make -j lang="$lang" model="$model" >/dev/null
|
||||||
checkLastCommand
|
checkLastCommand
|
||||||
rm -rf Objects >/dev/null
|
echo "Cleanup Temp files 1 for $model in $lang"
|
||||||
|
rm -rf Objects/Core >/dev/null
|
||||||
|
checkLastCommand
|
||||||
|
echo "Cleanup Temp files 2 for $model in $lang"
|
||||||
|
rm -rf Objects/Src >/dev/null
|
||||||
checkLastCommand
|
checkLastCommand
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user