Skip to content

Commit fe63034

Browse files
authored
Merge pull request #28 from FoamyGuy/type_annotations
adding type annotations
2 parents c157492 + 67117e8 commit fe63034

File tree

1 file changed

+65
-50
lines changed

1 file changed

+65
-50
lines changed

adafruit_ov2640.py

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@
4141

4242
from micropython import const
4343

44+
try:
45+
from typing import Optional, Union, Type, List
46+
from busio import I2C
47+
from microcontroller import Pin
48+
from circuitpython_typing import WriteableBuffer
49+
except ImportError:
50+
pass
51+
4452
CTRLI = const(0x50)
4553
_R_BYPASS = const(0x05)
4654
_QS = const(0x44)
@@ -954,17 +962,17 @@
954962

955963

956964
class _RegBits:
957-
def __init__(self, bank, reg, shift, mask):
965+
def __init__(self, bank: int, reg: int, shift: int, mask: int) -> None:
958966
self.bank = bank
959967
self.reg = reg
960968
self.shift = shift
961969
self.mask = mask
962970

963-
def __get__(self, obj, objtype=None):
971+
def __get__(self, obj: "_SCCBCameraBase", objtype: Optional[Type] = None) -> int:
964972
reg_value = obj._read_bank_register(self.bank, self.reg)
965973
return (reg_value >> self.shift) & self.mask
966974

967-
def __set__(self, obj, value):
975+
def __set__(self, obj: "_SCCBCameraBase", value: Union[bool, int]) -> None:
968976
if value & ~self.mask:
969977
raise ValueError(
970978
f"Value 0x{value:02x} does not fit in mask 0x{self.mask:02x}"
@@ -976,38 +984,38 @@ def __set__(self, obj, value):
976984

977985

978986
class _SCCBCameraBase: # pylint: disable=too-few-public-methods
979-
def __init__(self, i2c_bus, i2c_address):
987+
def __init__(self, i2c_bus: I2C, i2c_address: int) -> None:
980988
self._i2c_device = I2CDevice(i2c_bus, i2c_address)
981989
self._bank = None
982990

983-
def _get_reg_bits(self, bank, reg, shift, mask):
991+
def _get_reg_bits(self, bank: int, reg: int, shift: int, mask: int) -> int:
984992
return (self._read_bank_register(bank, reg) >> shift) & mask
985993

986-
def _set_reg_bits(
987-
self, bank, reg, shift, mask, value
988-
): # pylint: disable=too-many-arguments
994+
def _set_reg_bits( # pylint: disable=too-many-arguments
995+
self, bank: int, reg: int, shift: int, mask: int, value: int
996+
) -> None:
989997
reg_value = self._read_bank_register(bank, reg)
990998
reg_value &= ~(mask << shift)
991999
reg_value |= value << shift
9921000
self._write_register(reg, reg_value)
9931001

994-
def _write_list(self, reg_list):
1002+
def _write_list(self, reg_list: List[int]) -> None:
9951003
for i in range(0, len(reg_list), 2):
9961004
self._write_register(reg_list[i], reg_list[i + 1])
9971005
time.sleep(0.001)
9981006

999-
def _write_bank_register(self, bank, reg, value):
1007+
def _write_bank_register(self, bank: int, reg: int, value: int) -> None:
10001008
if self._bank != bank:
10011009
self._write_register(_BANK_SEL, bank)
10021010
self._write_register(reg, value)
10031011

1004-
def _read_bank_register(self, bank, reg):
1012+
def _read_bank_register(self, bank: int, reg: int) -> int:
10051013
if self._bank != bank:
10061014
self._write_register(_BANK_SEL, bank)
10071015
result = self._read_register(reg)
10081016
return result
10091017

1010-
def _write_register(self, reg, value):
1018+
def _write_register(self, reg: int, value: int) -> None:
10111019
if reg == _BANK_SEL:
10121020
if self._bank == value:
10131021
return
@@ -1019,7 +1027,7 @@ def _write_register(self, reg, value):
10191027
with self._i2c_device as i2c:
10201028
i2c.write(b)
10211029

1022-
def _read_register(self, reg):
1030+
def _read_register(self, reg: int) -> int:
10231031
b = bytearray(1)
10241032
b[0] = reg
10251033
with self._i2c_device as i2c:
@@ -1039,17 +1047,17 @@ class OV2640(_SCCBCameraBase): # pylint: disable=too-many-instance-attributes
10391047

10401048
def __init__(
10411049
self,
1042-
i2c_bus,
1043-
data_pins,
1044-
clock,
1045-
vsync,
1046-
href,
1047-
shutdown=None,
1048-
reset=None,
1049-
mclk=None,
1050-
mclk_frequency=20_000_000,
1051-
i2c_address=0x30,
1052-
size=OV2640_SIZE_QQVGA,
1050+
i2c_bus: I2C,
1051+
data_pins: Pin,
1052+
clock: Pin,
1053+
vsync: Pin,
1054+
href: Pin,
1055+
shutdown: Optional[Pin] = None,
1056+
reset: Optional[Pin] = None,
1057+
mclk: Optional[Pin] = None,
1058+
mclk_frequency: int = 20_000_000,
1059+
i2c_address: int = 0x30,
1060+
size: int = OV2640_SIZE_QQVGA,
10531061
): # pylint: disable=too-many-arguments
10541062
"""
10551063
Args:
@@ -1122,11 +1130,11 @@ def __init__(
11221130
data_pins=data_pins, clock=clock, vsync=vsync, href=href
11231131
)
11241132

1125-
def capture(self, buf):
1133+
def capture(self, buf: WriteableBuffer) -> Optional[memoryview]:
11261134
"""Capture an image into the buffer.
11271135
11281136
Args:
1129-
buf (Union[bytearray, memoryview]): A WritableBuffer to contain the \
1137+
buf (WriteableBuffer): A WritableBuffer to contain the \
11301138
captured image. Note that this can be a ulab array or a displayio Bitmap.
11311139
"""
11321140
self._imagecapture.capture(buf)
@@ -1138,40 +1146,40 @@ def capture(self, buf):
11381146
return None
11391147

11401148
@property
1141-
def capture_buffer_size(self):
1149+
def capture_buffer_size(self) -> int:
11421150
"""Return the size of capture buffer to use with current resolution & colorspace settings"""
11431151
if self.colorspace == OV2640_COLOR_JPEG:
11441152
return self.width * self.height // 5
11451153
return self.width * self.height * 2
11461154

11471155
@property
1148-
def mclk_frequency(self):
1156+
def mclk_frequency(self) -> Optional[int]:
11491157
"""Get the actual frequency the generated mclk, or None"""
11501158
return self._mclk_pwm.frequency if self._mclk_pwm else None
11511159

11521160
@property
1153-
def width(self):
1161+
def width(self) -> int:
11541162
"""Get the image width in pixels. A buffer of 2*width*height bytes \
11551163
stores a whole image."""
11561164
return self._w
11571165

11581166
@property
1159-
def height(self):
1167+
def height(self) -> int:
11601168
"""Get the image height in pixels. A buffer of 2*width*height bytes \
11611169
stores a whole image."""
11621170
return self._h
11631171

11641172
@property
1165-
def colorspace(self):
1173+
def colorspace(self) -> bytes:
11661174
"""Get or set the colorspace, one of the ``OV2640_COLOR_`` constants."""
11671175
return self._colorspace
11681176

11691177
@colorspace.setter
1170-
def colorspace(self, colorspace):
1178+
def colorspace(self, colorspace: bytes) -> None:
11711179
self._colorspace = colorspace
11721180
self._set_size_and_colorspace()
11731181

1174-
def _set_colorspace(self):
1182+
def _set_colorspace(self) -> None:
11751183
colorspace = self._colorspace
11761184
settings = _ov2640_color_settings[colorspace]
11771185

@@ -1180,7 +1188,7 @@ def _set_colorspace(self):
11801188
self._write_list(settings)
11811189
time.sleep(0.01)
11821190

1183-
def deinit(self):
1191+
def deinit(self) -> None:
11841192
"""Deinitialize the camera"""
11851193
self._imagecapture.deinit()
11861194
if self._mclk_pwm:
@@ -1191,11 +1199,11 @@ def deinit(self):
11911199
self._reset.deinit()
11921200

11931201
@property
1194-
def size(self):
1202+
def size(self) -> int:
11951203
"""Get or set the captured image size, one of the ``OV2640_SIZE_`` constants."""
11961204
return self._size
11971205

1198-
def _set_size_and_colorspace(self):
1206+
def _set_size_and_colorspace(self) -> None:
11991207
size = self._size
12001208
width, height, ratio = _resolution_info[size]
12011209
offset_x, offset_y, max_x, max_y = _ratio_table[ratio]
@@ -1218,11 +1226,11 @@ def _set_size_and_colorspace(self):
12181226
self._set_window(mode, offset_x, offset_y, max_x, max_y, width, height)
12191227

12201228
@size.setter
1221-
def size(self, size):
1229+
def size(self, size: int) -> None:
12221230
self._size = size
12231231
self._set_size_and_colorspace()
12241232

1225-
def _set_flip(self):
1233+
def _set_flip(self) -> None:
12261234
bits = 0
12271235
if self._flip_x:
12281236
bits |= _REG04_HFLIP_IMG
@@ -1231,38 +1239,45 @@ def _set_flip(self):
12311239
self._write_bank_register(_BANK_SENSOR, _REG04, _REG04_SET(bits))
12321240

12331241
@property
1234-
def flip_x(self):
1242+
def flip_x(self) -> bool:
12351243
"""Get or set the X-flip flag"""
12361244
return self._flip_x
12371245

12381246
@flip_x.setter
1239-
def flip_x(self, value):
1247+
def flip_x(self, value: bool) -> None:
12401248
self._flip_x = bool(value)
12411249
self._set_flip()
12421250

12431251
@property
1244-
def flip_y(self):
1252+
def flip_y(self) -> bool:
12451253
"""Get or set the Y-flip flag"""
12461254
return self._flip_y
12471255

12481256
@flip_y.setter
1249-
def flip_y(self, value):
1257+
def flip_y(self, value: bool) -> None:
12501258
self._flip_y = bool(value)
12511259
self._set_flip()
12521260

12531261
@property
1254-
def product_id(self):
1262+
def product_id(self) -> int:
12551263
"""Get the product id (PID) register. The expected value is 0x26."""
12561264
return self._read_bank_register(_BANK_SENSOR, _REG_PID)
12571265

12581266
@property
1259-
def product_version(self):
1260-
"""Get the version (VER) register. The expected value is 0x4x."""
1267+
def product_version(self) -> int:
1268+
"""Get the version (VER) register. The expected value is 0x41."""
12611269
return self._read_bank_register(_BANK_SENSOR, _REG_VER)
12621270

1263-
def _set_window(
1264-
self, mode, offset_x, offset_y, max_x, max_y, width, height
1265-
): # pylint: disable=too-many-arguments, too-many-locals
1271+
def _set_window( # pylint: disable=too-many-arguments, too-many-locals
1272+
self,
1273+
mode: int,
1274+
offset_x: int,
1275+
offset_y: int,
1276+
max_x: int,
1277+
max_y: int,
1278+
width: int,
1279+
height: int,
1280+
) -> None:
12661281
self._w = width
12671282
self._h = height
12681283

@@ -1335,7 +1350,7 @@ def _set_window(
13351350
self.test_pattern = self._test_pattern
13361351

13371352
@property
1338-
def exposure(self):
1353+
def exposure(self) -> int:
13391354
"""The exposure level of the sensor"""
13401355
aec_9_2 = self._get_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF)
13411356
aec_15_10 = self._get_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111)
@@ -1344,7 +1359,7 @@ def exposure(self):
13441359
return aec_1_0 | (aec_9_2 << 2) | (aec_15_10 << 10)
13451360

13461361
@exposure.setter
1347-
def exposure(self, exposure):
1362+
def exposure(self, exposure: int) -> None:
13481363
aec_1_0 = exposure & 0x11
13491364
aec_9_2 = (exposure >> 2) & 0b11111111
13501365
aec_15_10 = exposure >> 10

0 commit comments

Comments
 (0)