Support STC new serial STC8A8K64D4
1. Add 'stc8d' in option -P for STC8A8K64D4. 2. Add sub class Stc8dProtocol(Stc8Protocol) 3. Add override methods, choose_range, choose_trim, calibrate and build_options 4. To use: set stc8d for option -P. The frequency could be adjust from 1-45MHz. Pay attention to the unit of frequency is kHz.
This commit is contained in:
parent
2d3c24fc3a
commit
56d2629763
@ -33,6 +33,7 @@ from stcgal.protocols import Stc15Protocol
|
||||
from stcgal.protocols import Stc15AProtocol
|
||||
from stcgal.protocols import StcUsb15Protocol
|
||||
from stcgal.protocols import Stc8Protocol
|
||||
from stcgal.protocols import Stc8dProtocol
|
||||
from stcgal.protocols import StcAutoProtocol
|
||||
from stcgal.protocols import StcProtocolException
|
||||
from stcgal.protocols import StcFramingException
|
||||
@ -64,6 +65,9 @@ class StcGal:
|
||||
elif opts.protocol == "stc8":
|
||||
self.protocol = Stc8Protocol(opts.port, opts.handshake, opts.baud,
|
||||
round(opts.trim * 1000))
|
||||
elif opts.protocol == "stc8d":
|
||||
self.protocol = Stc8dProtocol(opts.port, opts.handshake, opts.baud,
|
||||
round(opts.trim * 1000))
|
||||
elif opts.protocol == "usb15":
|
||||
self.protocol = StcUsb15Protocol()
|
||||
else:
|
||||
@ -242,7 +246,7 @@ def cli():
|
||||
parser.add_argument("-a", "--autoreset", help="cycle power automatically by asserting DTR", action="store_true")
|
||||
parser.add_argument("-r", "--resetcmd", help="shell command for board power-cycling (instead of DTR assertion)", action="store")
|
||||
parser.add_argument("-P", "--protocol", help="protocol version (default: auto)",
|
||||
choices=["stc89", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "stc8", "usb15", "auto"], default="auto")
|
||||
choices=["stc89", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "stc8", "stc8d", "usb15", "auto"], default="auto")
|
||||
parser.add_argument("-p", "--port", help="serial port device", default="/dev/ttyUSB0")
|
||||
parser.add_argument("-b", "--baud", help="transfer baud rate (default: 19200)", type=BaudType(), default=19200)
|
||||
parser.add_argument("-l", "--handshake", help="handshake baud rate (default: 2400)", type=BaudType(), default=2400)
|
||||
|
@ -175,6 +175,7 @@ class MCUModelDatabase:
|
||||
MCUModel(name='STC8A8K56S4A12', magic=0xf627, total=65536, code=57344, eeprom=8192),
|
||||
MCUModel(name='STC8A8K60S4A12', magic=0xf629, total=65536, code=61440, eeprom=4096),
|
||||
MCUModel(name='STC8A8K64S4A12', magic=0xf628, total=65536, code=65024, eeprom=512),
|
||||
MCUModel(name='STC8A8K64D4', magic=0xf7f4,total=65536, code=65024, eeprom=512),
|
||||
MCUModel(name='STC15H4K08S4', magic=0xf601, total=65536, code=8192, eeprom=57344),
|
||||
MCUModel(name='STC15H4K16S4', magic=0xf602, total=65536, code=16384, eeprom=49152),
|
||||
MCUModel(name='STC15H4K24S4', magic=0xf603, total=65536, code=24576, eeprom=40960),
|
||||
|
@ -1874,3 +1874,151 @@ class StcUsb15Protocol(Stc15Protocol):
|
||||
if self.dev:
|
||||
self.write_packet(0xff)
|
||||
print("Disconnected!")
|
||||
|
||||
|
||||
class Stc8dProtocol(Stc8Protocol):
|
||||
"""Protocol handler for STC8A8K64D4 series"""
|
||||
|
||||
def __init__(self, port, handshake, baud, trim):
|
||||
Stc8Protocol.__init__(self, port, handshake, baud, trim)
|
||||
|
||||
def choose_range(self, packet, response, target_count):
|
||||
"""Choose appropriate trim value mean for next round from challenge
|
||||
responses."""
|
||||
|
||||
challenge_data = packet[2:]
|
||||
calib_data = response[2:]
|
||||
calib_len = response[1]
|
||||
if len(calib_data) < 2 * calib_len:
|
||||
raise StcProtocolException("range calibration data missing")
|
||||
|
||||
for i in range(calib_len >> 1):
|
||||
count_a, count_b = struct.unpack(
|
||||
">HH", calib_data[4 * i: 4 * i + 4])
|
||||
trim_a, trim_b, trim_range = struct.unpack(
|
||||
">BxBB", challenge_data[4 * i:4 * i + 4])
|
||||
if ((count_a <= target_count and count_b >= target_count)):
|
||||
target_trim = round(
|
||||
(target_count - count_a) * (trim_b - trim_a) / (count_b - count_a) + trim_a)
|
||||
# target_trim will be set at the center of packet in the 2nd calibration
|
||||
if target_trim < 6 or target_trim > 255 - 5:
|
||||
raise StcProtocolException("frequency trimming failed")
|
||||
return (target_trim, trim_range)
|
||||
|
||||
return None
|
||||
|
||||
def choose_trim(self, packet, response, target_count):
|
||||
"""Choose best trim for given target count from challenge
|
||||
responses."""
|
||||
|
||||
calib_data = response[2:]
|
||||
challenge_data = packet[2:]
|
||||
calib_len = response[1]
|
||||
if len(calib_data) < 2 * calib_len:
|
||||
raise StcProtocolException("trim calibration data missing")
|
||||
|
||||
best = None
|
||||
best_count = sys.maxsize
|
||||
for i in range(calib_len):
|
||||
count, = struct.unpack(">H", calib_data[2 * i: 2 * i + 2])
|
||||
trim_adj, trim_range = struct.unpack(
|
||||
">BB", challenge_data[2 * i: 2 * i + 2])
|
||||
if abs(count - target_count) < best_count:
|
||||
best_count = abs(count - target_count)
|
||||
best = (trim_adj, trim_range), count
|
||||
|
||||
if not best:
|
||||
raise StcProtocolException("frequency trimming failed")
|
||||
|
||||
return best
|
||||
|
||||
def calibrate(self):
|
||||
"""Calibrate selected user frequency frequency and switch to selected baudrate."""
|
||||
|
||||
# handle uncalibrated chips
|
||||
if self.mcu_clock_hz == 0 and self.trim_frequency <= 0:
|
||||
raise StcProtocolException(
|
||||
"uncalibrated, please provide a trim value")
|
||||
|
||||
# determine target counter
|
||||
user_speed = self.trim_frequency
|
||||
if user_speed <= 0:
|
||||
user_speed = self.mcu_clock_hz
|
||||
target_user_count = round(user_speed / self.baud_handshake)
|
||||
|
||||
# calibration, round 1
|
||||
print("Target frequency: ", end="")
|
||||
sys.stdout.flush()
|
||||
packet = bytes([0x00, 0x08])
|
||||
packet += bytes([0x00, 0x00, 0xFF, 0x00])
|
||||
packet += bytes([0x00, 0x10, 0xFF, 0x10])
|
||||
packet += bytes([0x00, 0x20, 0xFF, 0x20])
|
||||
packet += bytes([0x00, 0x30, 0xFF, 0x30])
|
||||
|
||||
self.write_packet(packet)
|
||||
self.pulse(b"\xfe", timeout=1.0)
|
||||
response = self.read_packet()
|
||||
if len(response) < 2 or response[0] != 0x00:
|
||||
raise StcProtocolException("incorrect magic in handshake packet")
|
||||
|
||||
# select ranges and trim values
|
||||
for divider in range(1, 6):
|
||||
user_trim = self.choose_range(
|
||||
packet, response, target_user_count * divider)
|
||||
if user_trim is not None:
|
||||
self.trim_divider = divider
|
||||
break
|
||||
if user_trim is None:
|
||||
raise StcProtocolException("frequency trimming unsuccessful")
|
||||
|
||||
# calibration, round 2
|
||||
packet = bytes([0x00, 0x0C])
|
||||
for i in range(-6, 6):
|
||||
packet += bytes([user_trim[0] + i, user_trim[1]])
|
||||
|
||||
self.write_packet(packet)
|
||||
self.pulse(b"\xfe", timeout=1.0)
|
||||
response = self.read_packet()
|
||||
if len(response) < 2 or response[0] != 0x00:
|
||||
raise StcProtocolException("incorrect magic in handshake packet")
|
||||
|
||||
# select final values
|
||||
user_trim, user_count = self.choose_trim(
|
||||
packet, response, target_user_count * self.trim_divider)
|
||||
self.trim_value = user_trim
|
||||
self.trim_frequency = round(
|
||||
user_count * self.baud_handshake/self.trim_divider)
|
||||
print("Target %.03f MHz" % (user_speed / 1E6))
|
||||
print("Adjusted frequency: %.03f MHz(%.03f%%)" % (
|
||||
(self.trim_frequency / 1E6), (self.trim_frequency*100/user_speed-100)))
|
||||
|
||||
# switch to programming frequency
|
||||
print("Switching to %d baud: " % self.baud_transfer, end="")
|
||||
sys.stdout.flush()
|
||||
packet = bytes([0x01, 0x00, 0x00])
|
||||
bauds = self.baud_transfer * 4
|
||||
packet += struct.pack(">H", round(65536 - 24E6 / bauds))
|
||||
packet += bytes([user_trim[1], user_trim[0]])
|
||||
# iap_wait = self.get_iap_delay(24E6)
|
||||
iap_wait = 0x98 # iap_wait for "STC8A8K64D4"
|
||||
packet += bytes([iap_wait])
|
||||
self.write_packet(packet)
|
||||
response = self.read_packet()
|
||||
if len(response) < 1 or response[0] != 0x01:
|
||||
raise StcProtocolException("incorrect magic in handshake packet")
|
||||
self.ser.baudrate = self.baud_transfer
|
||||
|
||||
def build_options(self):
|
||||
"""Build a packet of option data from the current configuration."""
|
||||
|
||||
msr = self.options.get_msr()
|
||||
packet = 40 * bytearray([0xff])
|
||||
packet[3] = 0x00
|
||||
packet[6] = 0x00
|
||||
packet[22] = 0x00
|
||||
packet[24:28] = struct.pack(">I", self.trim_frequency)
|
||||
packet[28:30] = self.trim_value
|
||||
packet[30] = self.trim_divider
|
||||
packet[32] = msr[0]
|
||||
packet[36:40] = msr[1:5]
|
||||
return bytes(packet)
|
||||
|
Loading…
Reference in New Issue
Block a user