From 12afa4bfd6782e0cc861e7385bd73be2481521ea Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 09:55:17 -0700 Subject: [PATCH 01/10] Working on adding type annotations --- adafruit_avrprog.py | 71 +++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index 704a258..028d408 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -32,10 +32,19 @@ __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AVRprog.git" -from digitalio import Direction, DigitalInOut +try: + from io import TextIOWrapper + from typing import Any, Dict, Optional -_SLOW_CLOCK = 100000 -_FAST_CLOCK = 1000000 + from _typeshed import FileDescriptorOrPath + from busio import SPI +except ImportError: + pass + +from digitalio import DigitalInOut, Direction + +_SLOW_CLOCK: int = 100000 +_FAST_CLOCK: int = 1000000 class AVRprog: @@ -86,10 +95,10 @@ class Boards: "fuse_mask": (0xFF, 0xFF, 0x07, 0x3F), } - _spi = None - _rst = None + _spi: SPI = None + _rst: DigitalInOut = None - def init(self, spi_bus, rst_pin): + def init(self, spi_bus: SPI, rst_pin) -> None: """ Initialize the programmer with an SPI port that will be used to communicate with the chip. Make sure your SPI supports 'write_readinto' @@ -100,7 +109,7 @@ def init(self, spi_bus, rst_pin): self._rst.direction = Direction.OUTPUT self._rst.value = True - def verify_sig(self, chip, verbose=False): + def verify_sig(self, chip: Dict[str, Any], verbose: bool = False) -> bool: """ Verify that the chip is connected properly, responds to commands, and has the correct signature. Returns True/False based on success @@ -115,7 +124,13 @@ def verify_sig(self, chip, verbose=False): return True # pylint: disable=too-many-branches - def program_file(self, chip, file_name, verbose=False, verify=True): + def program_file( + self, + chip: Dict[str, Any], + file_name: FileDescriptorOrPath, + verbose: bool = False, + verify: bool = True, + ) -> bool: """ Perform a chip erase and program from a file that contains Intel HEX data. Returns true on verify-success, False on @@ -132,10 +147,8 @@ def program_file(self, chip, file_name, verbose=False, verify=True): self.begin(clock=clock_speed) # create a file state dictionary - file_state = {"line": 0, "ext_addr": 0, "eof": False} - with open(file_name, "r") as file_state[ # pylint: disable=unspecified-encoding - "f" - ]: + file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": TextIOWrapper} + with open(file_name, "r") as file_state["f"]: page_size = chip["page_size"] for page_addr in range(0, chip["flash_size"], page_size): @@ -183,7 +196,9 @@ def program_file(self, chip, file_name, verbose=False, verify=True): self.end() return True - def verify_file(self, chip, file_name, verbose=False): + def verify_file( + self, chip: Dict[str, Any], file_name: FileDescriptorOrPath, verbose=False + ): """ Perform a chip full-flash verification from a file that contains Intel HEX data. Returns True/False on success/fail. @@ -192,10 +207,8 @@ def verify_file(self, chip, file_name, verbose=False): raise RuntimeError("Signature read failure") # create a file state dictionary - file_state = {"line": 0, "ext_addr": 0, "eof": False} - with open(file_name, "r") as file_name[ # pylint: disable=unspecified-encoding - "f" - ]: + file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": TextIOWrapper} + with open(file_name, "r") as file_name["f"]: page_size = chip["page_size"] clock_speed = chip.get("clock_speed", _FAST_CLOCK) self.begin(clock=clock_speed) @@ -230,9 +243,9 @@ def verify_file(self, chip, file_name, verbose=False): self.end() return True - def read_fuses(self, chip): + def read_fuses(self, chip: Dict[str, Any]) -> tuple: """ - Read the 4 fuses and return them in a list (low, high, ext, lock) + Read the 4 fuses and return them in a tuple (low, high, ext, lock) Each fuse is bitwise-&'s with the chip's fuse mask for simplicity """ mask = chip["fuse_mask"] @@ -245,7 +258,14 @@ def read_fuses(self, chip): return (low, high, ext, lock) # pylint: disable=unused-argument,too-many-arguments - def write_fuses(self, chip, low=None, high=None, ext=None, lock=None): + def write_fuses( + self, + chip: Dict[str, Any], + low: Optional[int] = None, + high: Optional[int] = None, + ext: Optional[int] = None, + lock: Optional[int] = None, + ) -> None: """ Write any of the 4 fuses. If the kwarg low/high/ext/lock is not passed in or is None, that fuse is skipped @@ -260,7 +280,14 @@ def write_fuses(self, chip, low=None, high=None, ext=None, lock=None): self.end() # pylint: disable=too-many-arguments - def verify_fuses(self, chip, low=None, high=None, ext=None, lock=None): + def verify_fuses( + self, + chip: Dict[str, Any], + low: Optional[int] = None, + high: Optional[int] = None, + ext: Optional[int] = None, + lock: Optional[int] = None, + ) -> bool: """ Verify the 4 fuses. If the kwarg low/high/ext/lock is not passed in or is None, that fuse is not checked. @@ -286,7 +313,7 @@ def erase_chip(self): #################### Mid level - def begin(self, clock=_FAST_CLOCK): + def begin(self, clock: int = _FAST_CLOCK) -> None: """ Begin programming mode: pull reset pin low, initialize SPI, and send the initialization command to get the AVR's attention. From 907ab2da5613f57563f5df11083659a81e1610b8 Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 09:56:43 -0700 Subject: [PATCH 02/10] Suspected bug fix where file_name was being assigned as textio during open operation rather than a field in file_state dictionary --- adafruit_avrprog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index 028d408..91f0580 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -208,7 +208,7 @@ def verify_file( # create a file state dictionary file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": TextIOWrapper} - with open(file_name, "r") as file_name["f"]: + with open(file_name, "r") as file_state["f"]: page_size = chip["page_size"] clock_speed = chip.get("clock_speed", _FAST_CLOCK) self.begin(clock=clock_speed) From bfe4c39f7501f7fefa6ea895724247f8fbbe79e0 Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 12:05:52 -0700 Subject: [PATCH 03/10] Completing type annotations --- adafruit_avrprog.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index 91f0580..b881d03 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -34,13 +34,15 @@ try: from io import TextIOWrapper - from typing import Any, Dict, Optional + from typing import Any, Dict, Optional, Tuple from _typeshed import FileDescriptorOrPath from busio import SPI except ImportError: pass +from math import floor + from digitalio import DigitalInOut, Direction _SLOW_CLOCK: int = 100000 @@ -324,14 +326,14 @@ def begin(self, clock: int = _FAST_CLOCK) -> None: self._spi.configure(baudrate=clock) self._transaction((0xAC, 0x53, 0, 0)) - def end(self): + def end(self) -> None: """ End programming mode: SPI is released, and reset pin set high. """ self._spi.unlock() self._rst.value = True - def read_signature(self): + def read_signature(self) -> list: """ Read and return the signature of the chip as two bytes in an array. Requires calling begin() beforehand to put in programming mode. @@ -342,7 +344,7 @@ def read_signature(self): sig.append(self._transaction((0x30, 0, i, 0))[2]) return sig - def read(self, addr, read_buffer): + def read(self, addr: int, read_buffer: bytearray) -> None: """ Read a chunk of memory from address 'addr'. The amount read is the same as the size of the bytearray 'read_buffer'. Data read is placed @@ -366,13 +368,15 @@ def read(self, addr, read_buffer): last_addr = read_addr #################### Low level - def _flash_word(self, addr, low, high): + def _flash_word(self, addr: int, low: int, high: int) -> None: self._transaction((0x40, addr >> 8, addr, low)) self._transaction((0x48, addr >> 8, addr, high)) - def _flash_page(self, page_buffer, page_addr, page_size): + def _flash_page( + self, page_buffer: bytearray, page_addr: int, page_size: int + ) -> None: page_addr //= 2 # address is by 'words' not bytes! - for i in range(page_size / 2): # page indexed by words, not bytes + for i in range(floor(page_size / 2)): # page indexed by words, not bytes lo_byte, hi_byte = page_buffer[2 * i : 2 * i + 2] self._flash_word(i, lo_byte, hi_byte) @@ -384,23 +388,25 @@ def _flash_page(self, page_buffer, page_addr, page_size): raise RuntimeError("Failed to commit page to flash") self._busy_wait() - def _transaction(self, command): + def _transaction(self, command: Tuple[int, int, int, int]) -> bytes: reply = bytearray(4) - command = bytearray([i & 0xFF for i in command]) + command_bytes = bytearray([i & 0xFF for i in command]) - self._spi.write_readinto(command, reply) - # s = [hex(i) for i in command] - # print("Sending %s reply %s" % ([hex(i) for i in command], [hex(i) for i in reply])) - if reply[2] != command[1]: + self._spi.write_readinto(command_bytes, reply) + # s = [hex(i) for i in command_bytes] + # print("Sending %s reply %s" % ([hex(i) for i in command_bytes], [hex(i) for i in reply])) + if reply[2] != command_bytes[1]: raise RuntimeError("SPI transaction failed") return reply[1:] # first byte is ignored - def _busy_wait(self): + def _busy_wait(self) -> None: while self._transaction((0xF0, 0, 0, 0))[2] & 0x01: pass -def read_hex_page(file_state, page_addr, page_size, page_buffer): +def read_hex_page( + file_state: Dict[str, Any], page_addr: int, page_size: int, page_buffer: bytearray +) -> bool: # pylint: disable=too-many-branches """ Helper function that does the Intel Hex parsing. Takes in a dictionary From 0b3e5f861d9f3146d149496c9b8d952efb58ebc6 Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 12:15:07 -0700 Subject: [PATCH 04/10] Fixing optional import that was, actually, not optional. --- adafruit_avrprog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index b881d03..b930689 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -37,12 +37,12 @@ from typing import Any, Dict, Optional, Tuple from _typeshed import FileDescriptorOrPath - from busio import SPI except ImportError: pass from math import floor +from busio import SPI from digitalio import DigitalInOut, Direction _SLOW_CLOCK: int = 100000 From 054823d5a6421983c5836e5cfa443c7ba7a10a1e Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 12:48:49 -0700 Subject: [PATCH 05/10] Working on optional imports --- adafruit_avrprog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index b930689..80a09f9 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -33,15 +33,15 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AVRprog.git" try: - from io import TextIOWrapper from typing import Any, Dict, Optional, Tuple - from _typeshed import FileDescriptorOrPath except ImportError: pass +from io import TextIOWrapper from math import floor +from _typeshed import FileDescriptorOrPath from busio import SPI from digitalio import DigitalInOut, Direction From 080462ebd57ec06a4ff5a9010549745076c73dd3 Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 13:00:55 -0700 Subject: [PATCH 06/10] Working around missing _typeshed package --- adafruit_avrprog.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index 80a09f9..bbd5762 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -33,15 +33,22 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AVRprog.git" try: - from typing import Any, Dict, Optional, Tuple + from os import PathLike + from typing import Any, Dict, Optional, Tuple, TypeAlias + + # Technically this type should come from: from _typeshed import FileDescriptorOrPath + # Unfortunately _typeshed is only in the standard library in newer releases of Python, e.g. 3.11 + # Thus have to define a placeholder + FileDescriptorOrPath: TypeAlias = ( + int | str | bytes | PathLike[str] | PathLike[bytes] + ) + from io import TextIOWrapper except ImportError: pass -from io import TextIOWrapper from math import floor -from _typeshed import FileDescriptorOrPath from busio import SPI from digitalio import DigitalInOut, Direction From f6d41b6236e0f570563294655b1f5dc151fe98a4 Mon Sep 17 00:00:00 2001 From: Ross Kukard <75049118+RossK1@users.noreply.github.com> Date: Tue, 25 Apr 2023 13:34:41 -0700 Subject: [PATCH 07/10] finalizing (hopefully) all type hinting --- adafruit_avrprog.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index bbd5762..b0ed8fd 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -34,7 +34,7 @@ try: from os import PathLike - from typing import Any, Dict, Optional, Tuple, TypeAlias + from typing import Any, Dict, List, Optional, Tuple, TypeAlias, Union # Technically this type should come from: from _typeshed import FileDescriptorOrPath # Unfortunately _typeshed is only in the standard library in newer releases of Python, e.g. 3.11 @@ -49,7 +49,7 @@ from math import floor -from busio import SPI +from busio import I2C, SPI from digitalio import DigitalInOut, Direction _SLOW_CLOCK: int = 100000 @@ -107,7 +107,7 @@ class Boards: _spi: SPI = None _rst: DigitalInOut = None - def init(self, spi_bus: SPI, rst_pin) -> None: + def init(self, spi_bus: SPI, rst_pin: Union[SPI, I2C]) -> None: """ Initialize the programmer with an SPI port that will be used to communicate with the chip. Make sure your SPI supports 'write_readinto' @@ -206,8 +206,11 @@ def program_file( return True def verify_file( - self, chip: Dict[str, Any], file_name: FileDescriptorOrPath, verbose=False - ): + self, + chip: Dict[str, Any], + file_name: FileDescriptorOrPath, + verbose: bool = False, + ) -> bool: """ Perform a chip full-flash verification from a file that contains Intel HEX data. Returns True/False on success/fail. @@ -252,12 +255,12 @@ def verify_file( self.end() return True - def read_fuses(self, chip: Dict[str, Any]) -> tuple: + def read_fuses(self, chip: Dict[str, Any]) -> Tuple[int, int, int, int]: """ Read the 4 fuses and return them in a tuple (low, high, ext, lock) Each fuse is bitwise-&'s with the chip's fuse mask for simplicity """ - mask = chip["fuse_mask"] + mask: Tuple[int, int, int, int] = chip["fuse_mask"] self.begin(clock=_SLOW_CLOCK) low = self._transaction((0x50, 0, 0, 0))[2] & mask[0] high = self._transaction((0x58, 0x08, 0, 0))[2] & mask[1] @@ -311,7 +314,7 @@ def verify_fuses( return False return True - def erase_chip(self): + def erase_chip(self) -> None: """ Fully erases the chip. """ @@ -340,7 +343,7 @@ def end(self) -> None: self._spi.unlock() self._rst.value = True - def read_signature(self) -> list: + def read_signature(self) -> List[int]: """ Read and return the signature of the chip as two bytes in an array. Requires calling begin() beforehand to put in programming mode. @@ -395,7 +398,7 @@ def _flash_page( raise RuntimeError("Failed to commit page to flash") self._busy_wait() - def _transaction(self, command: Tuple[int, int, int, int]) -> bytes: + def _transaction(self, command: Tuple[int, int, int, int]) -> bytearray: reply = bytearray(4) command_bytes = bytearray([i & 0xFF for i in command]) From 8e1213344e0095490aea9e4a46e73d22c4169b1a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 6 May 2024 10:29:46 -0500 Subject: [PATCH 08/10] review feedback changes --- adafruit_avrprog.py | 50 +++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index b0ed8fd..f78c815 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -33,23 +33,47 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AVRprog.git" try: + from typing import Any, Dict, List, Optional, Tuple, Union, TypedDict + from typing_extensions import TypeAlias from os import PathLike - from typing import Any, Dict, List, Optional, Tuple, TypeAlias, Union + from busio import SPI + from microcontroller import Pin # Technically this type should come from: from _typeshed import FileDescriptorOrPath # Unfortunately _typeshed is only in the standard library in newer releases of Python, e.g. 3.11 # Thus have to define a placeholder - FileDescriptorOrPath: TypeAlias = ( - int | str | bytes | PathLike[str] | PathLike[bytes] - ) + FileDescriptorOrPath: TypeAlias = Union[ + int, str, bytes, PathLike[str], PathLike[bytes] + ] + from io import TextIOWrapper + class ChipDictionary(TypedDict): + """ + Dictionary representing a specific target chip type + """ + + name: str + sig: List[int] + flash_size: int + page_size: int + fuse_mask: Tuple[int] + + class FileState(TypedDict): + """ + Dictionary representing a File State + """ + + # pylint: disable=invalid-name + line: int + ext_addr: int + eof: bool + f: Optional[TextIOWrapper] + except ImportError: pass -from math import floor -from busio import I2C, SPI from digitalio import DigitalInOut, Direction _SLOW_CLOCK: int = 100000 @@ -104,10 +128,10 @@ class Boards: "fuse_mask": (0xFF, 0xFF, 0x07, 0x3F), } - _spi: SPI = None - _rst: DigitalInOut = None + _spi: Optional[SPI] = None + _rst: Optional[DigitalInOut] = None - def init(self, spi_bus: SPI, rst_pin: Union[SPI, I2C]) -> None: + def init(self, spi_bus: SPI, rst_pin: Pin) -> None: """ Initialize the programmer with an SPI port that will be used to communicate with the chip. Make sure your SPI supports 'write_readinto' @@ -118,7 +142,7 @@ def init(self, spi_bus: SPI, rst_pin: Union[SPI, I2C]) -> None: self._rst.direction = Direction.OUTPUT self._rst.value = True - def verify_sig(self, chip: Dict[str, Any], verbose: bool = False) -> bool: + def verify_sig(self, chip: ChipDictionary, verbose: bool = False) -> bool: """ Verify that the chip is connected properly, responds to commands, and has the correct signature. Returns True/False based on success @@ -156,7 +180,7 @@ def program_file( self.begin(clock=clock_speed) # create a file state dictionary - file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": TextIOWrapper} + file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": None} with open(file_name, "r") as file_state["f"]: page_size = chip["page_size"] @@ -219,7 +243,7 @@ def verify_file( raise RuntimeError("Signature read failure") # create a file state dictionary - file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": TextIOWrapper} + file_state = {"line": 0, "ext_addr": 0, "eof": False, "f": None} with open(file_name, "r") as file_state["f"]: page_size = chip["page_size"] clock_speed = chip.get("clock_speed", _FAST_CLOCK) @@ -386,7 +410,7 @@ def _flash_page( self, page_buffer: bytearray, page_addr: int, page_size: int ) -> None: page_addr //= 2 # address is by 'words' not bytes! - for i in range(floor(page_size / 2)): # page indexed by words, not bytes + for i in range(page_size / 2): # page indexed by words, not bytes lo_byte, hi_byte = page_buffer[2 * i : 2 * i + 2] self._flash_word(i, lo_byte, hi_byte) From 1b12ff5c6375ea9d5df6132e0de6a86ad1f43e1b Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 6 May 2024 10:38:24 -0500 Subject: [PATCH 09/10] use TypedDict definitions for args --- adafruit_avrprog.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index f78c815..0ff7bc6 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -33,7 +33,7 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AVRprog.git" try: - from typing import Any, Dict, List, Optional, Tuple, Union, TypedDict + from typing import List, Optional, Tuple, Union, TypedDict from typing_extensions import TypeAlias from os import PathLike from busio import SPI @@ -57,7 +57,7 @@ class ChipDictionary(TypedDict): sig: List[int] flash_size: int page_size: int - fuse_mask: Tuple[int] + fuse_mask: Tuple[int, int, int, int] class FileState(TypedDict): """ @@ -159,7 +159,7 @@ def verify_sig(self, chip: ChipDictionary, verbose: bool = False) -> bool: # pylint: disable=too-many-branches def program_file( self, - chip: Dict[str, Any], + chip: ChipDictionary, file_name: FileDescriptorOrPath, verbose: bool = False, verify: bool = True, @@ -231,7 +231,7 @@ def program_file( def verify_file( self, - chip: Dict[str, Any], + chip: ChipDictionary, file_name: FileDescriptorOrPath, verbose: bool = False, ) -> bool: @@ -279,7 +279,7 @@ def verify_file( self.end() return True - def read_fuses(self, chip: Dict[str, Any]) -> Tuple[int, int, int, int]: + def read_fuses(self, chip: ChipDictionary) -> Tuple[int, int, int, int]: """ Read the 4 fuses and return them in a tuple (low, high, ext, lock) Each fuse is bitwise-&'s with the chip's fuse mask for simplicity @@ -296,7 +296,7 @@ def read_fuses(self, chip: Dict[str, Any]) -> Tuple[int, int, int, int]: # pylint: disable=unused-argument,too-many-arguments def write_fuses( self, - chip: Dict[str, Any], + chip: ChipDictionary, low: Optional[int] = None, high: Optional[int] = None, ext: Optional[int] = None, @@ -318,7 +318,7 @@ def write_fuses( # pylint: disable=too-many-arguments def verify_fuses( self, - chip: Dict[str, Any], + chip: ChipDictionary, low: Optional[int] = None, high: Optional[int] = None, ext: Optional[int] = None, @@ -439,7 +439,7 @@ def _busy_wait(self) -> None: def read_hex_page( - file_state: Dict[str, Any], page_addr: int, page_size: int, page_buffer: bytearray + file_state: FileState, page_addr: int, page_size: int, page_buffer: bytearray ) -> bool: # pylint: disable=too-many-branches """ From 2493023c5506b1f8376f2bbd095a573351d69e61 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 6 May 2024 11:28:24 -0500 Subject: [PATCH 10/10] use int division --- adafruit_avrprog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_avrprog.py b/adafruit_avrprog.py index 0ff7bc6..656e104 100644 --- a/adafruit_avrprog.py +++ b/adafruit_avrprog.py @@ -410,7 +410,7 @@ def _flash_page( self, page_buffer: bytearray, page_addr: int, page_size: int ) -> None: page_addr //= 2 # address is by 'words' not bytes! - for i in range(page_size / 2): # page indexed by words, not bytes + for i in range(page_size // 2): # page indexed by words, not bytes lo_byte, hi_byte = page_buffer[2 * i : 2 * i + 2] self._flash_word(i, lo_byte, hi_byte)