Skip to content

Commit 5fb0bde

Browse files
committed
First bug fix
1 parent 0a29c1b commit 5fb0bde

File tree

3 files changed

+147
-86
lines changed

3 files changed

+147
-86
lines changed

PT2258.py

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55

66
class PT2258:
77
# Constants for volume, attenuation levels, and mute, clear registers.
8-
# These constants are defined using the const() function from micropython
9-
# to save memory on the microcontroller.
8+
# These constants are defined using the const() function from micropython to save memory on the microcontroller.
9+
10+
# Constants for clear registers
1011
__CLEAR_REGISTER: int = const(0xC0)
12+
13+
# Constants for master volume registers 10dB
14+
__MUTE_REGISTER: int = const(0xF8)
15+
16+
# Constants for master volume registers 10dB
1117
__MASTER_VOLUME_10DB: int = const(0xD0)
1218
__MASTER_VOLUME_1DB: int = const(0xE0)
13-
__MUTE_REGISTER: int = const(0xF8)
1419

1520
# Constants for channel registers 10dB
1621
__C1_10DB = const(0x80)
@@ -41,18 +46,20 @@ def __init__(self, port: I2C = None, address: int = 0x88) -> None:
4146
"""
4247
# Check if the I2C object and address are valid.
4348
if port is None:
44-
raise ValueError("The 'port' I2C object is required to initialize PT2258.")
49+
raise ValueError("The I2C object 'port' is missing!")
4550
if address not in [0x8C, 0x88, 0x84, 0x80]:
4651
raise ValueError(
4752
f"Invalid PT2258 device address {address}. It should be 0x8C, 0x88, 0x84, or 0x80."
4853
)
4954

5055
# Store the I2C object and PT2258 address as class attributes.
5156
self.__I2C: I2C = port
57+
58+
# PT2258 only accept 7 bits address.
5259
self.__PT2258_ADDR: int = const(address >> 1)
5360

5461
# Define channel registers for both 10dB and 1dB settings.
55-
self.__CHANNEL_REGISTERS: tuple = (
62+
self.__CHANNEL_REGISTERS: tuple[tuple[int, int], ...] = (
5663
(self.__C1_10DB, self.__C1_1DB), # channel 1 (10dB, 1dB)
5764
(self.__C2_10DB, self.__C2_1DB), # channel 2 (10dB, 1dB)
5865
(self.__C3_10DB, self.__C3_1DB), # channel 3 (10dB, 1dB)
@@ -64,8 +71,12 @@ def __init__(self, port: I2C = None, address: int = 0x88) -> None:
6471
# Initialize the last_ack variable to keep track of the last acknowledgment.
6572
self.__last_ack: int = 0
6673

67-
# Initialize the PT2258 by calling the __initialize_pt2258() method.
68-
self.__initialize_pt2258()
74+
# Initialize the PT2258 by calling the "initialize_pt2258()" method.
75+
self.__last_ack = self.__initialize_pt2258()
76+
if self.__last_ack != 1:
77+
raise RuntimeError(
78+
"Failed to initialize PT2258! Please double check the I2C connection's."
79+
)
6980

7081
def __write_pt2258(self, write_data: int) -> int:
7182
"""
@@ -77,21 +88,21 @@ def __write_pt2258(self, write_data: int) -> int:
7788
:return: acknowledgment from slave (PT2258)
7889
"""
7990
try:
80-
# Try to write the instruction data to the PT2258 via I2C.
91+
# Try to write the instruction to the PT2258 via I2C.
8192
ack: int = self.__I2C.writeto(self.__PT2258_ADDR, bytes([write_data]))
8293
except OSError as error:
8394
# Handle communication errors and raise a RuntimeError.
8495
if error.args[0] == 5:
8596
raise RuntimeError(
86-
"Communication error with the PT2258 during the operation."
97+
"Communication error with the PT2258 during the operation!"
8798
)
8899
else:
89100
raise RuntimeError(
90-
f"Communication error with the PT2258. Error message: {error}"
101+
f"Communication error with the PT2258! Error message: {error}"
91102
)
92103
return ack
93104

94-
def __initialize_pt2258(self) -> None:
105+
def __initialize_pt2258(self) -> int:
95106
"""
96107
Initialize the PT2258 6-channel volume controller IC.
97108
@@ -102,7 +113,7 @@ def __initialize_pt2258(self) -> None:
102113
it is recommended to clear the register "C0H" as the first step of initialization.
103114
104115
:raises OSError: If the PT2258 device is not present on the I2C bus.
105-
:return: None
116+
:return: acknowledgment from slave (PT2258)
106117
"""
107118
# Wait for at least 300ms for stability after power-on.
108119
utime.sleep_ms(300)
@@ -112,7 +123,8 @@ def __initialize_pt2258(self) -> None:
112123
raise OSError("PT2258 not found on the I2C bus.")
113124

114125
# Clear the specified register to initialize the PT2258.
115-
self.__write_pt2258(self.__CLEAR_REGISTER)
126+
self.__last_ack = self.__write_pt2258(self.__CLEAR_REGISTER)
127+
return self.__last_ack
116128

117129
def master_volume(self, volume: int = 0) -> int:
118130
"""
@@ -121,7 +133,7 @@ def master_volume(self, volume: int = 0) -> int:
121133
:param volume: The desired master volume level (0 to 79).
122134
:type volume: int
123135
:raises ValueError: If the provided volume is outside the range 0 to 79.
124-
:return: int
136+
:return: acknowledgment from slave (PT2258)
125137
"""
126138
# Validate the volume input.
127139
if not 0 <= volume <= 79:
@@ -131,13 +143,9 @@ def master_volume(self, volume: int = 0) -> int:
131143
att_10db, att_1db = divmod(79 - volume, 10)
132144

133145
# Send attenuation settings to the PT2258, first 10dB and then 1dB.
134-
self.__last_ack: int = self.__write_pt2258(
135-
self.__MASTER_VOLUME_10DB | att_10db,
136-
)
146+
self.__last_ack = self.__write_pt2258(self.__MASTER_VOLUME_10DB | att_10db)
137147
if self.__last_ack:
138-
self.__last_ack: int = self.__write_pt2258(
139-
self.__MASTER_VOLUME_1DB | att_1db
140-
)
148+
self.__last_ack = self.__write_pt2258(self.__MASTER_VOLUME_1DB | att_1db)
141149
return self.__last_ack
142150

143151
def channel_volume(self, channel: int, volume: int = 0) -> int:
@@ -149,7 +157,7 @@ def channel_volume(self, channel: int, volume: int = 0) -> int:
149157
:param volume: The desired volume level for the channel (0 to 79).
150158
:type volume: int
151159
:raises ValueError: If the provided channel or volume is outside the valid range.
152-
:return: int
160+
:return: acknowledgment from slave (PT2258)
153161
"""
154162
# Validate the channel and volume inputs.
155163
if not 0 <= volume <= 79:
@@ -166,9 +174,9 @@ def channel_volume(self, channel: int, volume: int = 0) -> int:
166174
att_10db, att_1db = divmod(79 - volume, 10)
167175

168176
# Send attenuation settings to the PT2258, first 10dB and then 1dB.
169-
self.__last_ack: int = self.__write_pt2258(channel_10db | att_10db)
177+
self.__last_ack = self.__write_pt2258(channel_10db | att_10db)
170178
if self.__last_ack:
171-
self.__last_ack: int = self.__write_pt2258(channel_1db | att_1db)
179+
self.__last_ack = self.__write_pt2258(channel_1db | att_1db)
172180
return self.__last_ack
173181

174182
def mute(self, status: bool = False) -> int:
@@ -178,7 +186,7 @@ def mute(self, status: bool = False) -> int:
178186
:param status: If True, mute is enabled. If False, mute is disabled.
179187
:type status: bool
180188
:raises ValueError: If the provided status is not a boolean value.
181-
:return: int
189+
:return: acknowledgment from slave (PT2258)
182190
"""
183191
# Validate the mute status input.
184192
if not isinstance(status, bool):
@@ -187,5 +195,5 @@ def mute(self, status: bool = False) -> int:
187195
)
188196

189197
# Send the mute status to the PT2258 and store the acknowledgment.
190-
self.__last_ack: int = self.__write_pt2258(self.__MUTE_REGISTER | status)
198+
self.__last_ack = self.__write_pt2258(self.__MUTE_REGISTER | status)
191199
return self.__last_ack

README.md

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Ground, it is set to “0”. Please refer to the information below:
6262
|-----------|-------|-------|---------------------|
6363
| 1 | 1 | 1 | 8CH |
6464
| 2 | 1 | 0 | 88H |
65-
| 3 | 0 | 0 | 84H |
65+
| 3 | 0 | 1 | 84H |
6666
| 4 | 0 | 0 | 80H |
6767

6868
### Find PT2258
@@ -123,64 +123,89 @@ import utime
123123
from PT2258 import PT2258
124124
from machine import Pin, I2C
125125

126-
# Create an I2C object for communication with PT2258
127-
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
126+
"""
127+
This code explains how to use the class methods and how to use the acknowledgments bit from the slave (PT2258).
128+
This is overkill but whynot?
129+
"""
128130

129-
# Create an instance of the PT2258 class
130-
pt2258 = PT2258(port=i2c, address=0x88)
131+
if __name__ == "__main__":
132+
# Create an I2C object for communication with PT2258
133+
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
131134

135+
# Create an instance of the PT2258 class
136+
pt2258 = PT2258(port=i2c, address=0x88)
132137

133-
def main() -> None:
134-
"""
135-
Main function for testing the PT2258 volume controller.
136-
137-
This function initializes the PT2258, sets all channels to zero volume, and then gradually increases and decreases
138-
the master volume to simulate a volume control action.
139-
140-
:return: None
141-
"""
142-
143-
print('Hello, world!')
138+
# This variable is used to track the last acknowledgments from PT2258.
139+
# This helps to minimize data bottleneck, I2C overhead.
140+
last_ack: int = 0
141+
142+
print("Hello, world!")
144143
utime.sleep(2)
145-
print('PT2258 test script starting...')
144+
print("PT2258 test script starting...")
146145
utime.sleep(5)
147146

148-
# Set all channels to 0 volume
147+
# Set all channels' volume to 0
149148
for channel in range(6):
150-
pt2258.channel_volume(channel, 0)
151-
pt2258.master_volume(0)
149+
last_ack = pt2258.channel_volume(channel, 0)
150+
# We need to wait for acknowledgments.
151+
while last_ack:
152+
pass
153+
last_ack = pt2258.master_volume(0)
154+
while last_ack:
155+
pass
152156

153157
while True:
154158
# The following loops simulate volume changes, similar to a rotary encoder or potentiometer.
155159

156-
# Increase volume
160+
# Increase master volume.
157161
for volume in range(80):
158-
print('Volume is at maximum' if volume == 79 else f'Master volume: {volume}dB')
159-
pt2258.master_volume(volume)
160-
utime.sleep(0.5) # Wait for half a second before the next volume change
162+
last_ack = pt2258.master_volume(volume)
163+
if last_ack:
164+
print(
165+
f"Master volume: {volume} Volume is at maximum"
166+
if volume == 79
167+
else f"Master volume: {volume}dB"
168+
)
169+
170+
# We need to wait for next acknowledgments from PT2258.
171+
while last_ack:
172+
pass
173+
utime.sleep(0.5) # Wait for half a second before the next volume change.
174+
utime.sleep(10)
161175

162-
# Decrease volume
176+
# Decrease master volume
163177
for volume in range(80):
164-
print('Volume is at maximum' if volume == 79 else f'Master volume: -{volume}dB')
165-
pt2258.master_volume(79 - volume)
178+
last_ack = pt2258.master_volume(79 - volume)
179+
if last_ack:
180+
print(
181+
f"Master volume: {volume} Volume is at maximum"
182+
if volume == 79
183+
else f"Master volume: -{volume}dB"
184+
)
185+
186+
# We need to wait for next acknowledgments from PT2258.
187+
while last_ack:
188+
pass
166189
utime.sleep(0.5) # Wait for half a second before the next volume change
167190

168191
# Set volume to maximum
169-
print('Volume at maximum')
170-
pt2258.master_volume(79)
192+
last_ack = pt2258.master_volume(79)
193+
if last_ack:
194+
print("Volume at maximum")
171195
utime.sleep(10)
172196

173197
# Mute and UnMute
174-
print('Muted. Please wait...')
175-
pt2258.mute(True)
198+
last_ack = pt2258.mute(True)
199+
if last_ack:
200+
print("Muted. Please wait...")
176201
utime.sleep(5)
177-
print('UnMuted')
178-
pt2258.mute(False)
179-
utime.sleep(10)
180202

203+
last_ack = pt2258.mute(False)
204+
if last_ack:
205+
print("UnMuted")
206+
utime.sleep(10)
181207

182-
if __name__ == '__main__':
183-
main()
208+
# This code is just simulating how to use the class methods. Please refer to the README.md/Usage/.
184209
```
185210

186211
Feel free to explore and adapt these examples to suit your specific project requirements.
@@ -252,9 +277,9 @@ the [repository](https://github.com/zerovijay/PT2258).
252277
The class methods are documented in the `PT2258` class documentation. It includes the following methods:
253278

254279
- `__init__(self, port: I2C = None, address: int = None) -> None`: Initialize the PT2258 instance.
255-
- `master_volume(self, volume: int) -> None`: Set the master volume level.
256-
- `channel_volume(self, channel: int, volume: int) -> None`: Set the specific channel volume.
257-
- `mute(self, status: bool = False) -> None`: Enable or disable the mute functionality.
280+
- `master_volume(self, volume: int) -> int`: Set the master volume level.
281+
- `channel_volume(self, channel: int, volume: int) -> int`: Set the specific channel volume.
282+
- `mute(self, status: bool = False) -> int`: Enable or disable the mute functionality.
258283

259284
# Contributions
260285

0 commit comments

Comments
 (0)