PyQa40x-i2c 0.3.0__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/PKG-INFO +1 -1
  2. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/RELEASE_NOTES.md +8 -0
  3. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/_version.py +3 -3
  4. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/analyzer.py +21 -0
  5. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/stream.py +26 -14
  6. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x_i2c.egg-info/PKG-INFO +1 -1
  7. pyqa40x_i2c-0.3.2/src/PyQa40x_i2c.egg-info/scm_version.json +8 -0
  8. pyqa40x_i2c-0.3.0/src/PyQa40x_i2c.egg-info/scm_version.json +0 -8
  9. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/.github/workflows/code_checker.yml +0 -0
  10. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/.github/workflows/publish_package.yml +0 -0
  11. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/.github/workflows/unit_tests.yml +0 -0
  12. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/.gitignore +0 -0
  13. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/.pylint_ignore +0 -0
  14. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LICENSE +0 -0
  15. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/FirstPrinciples.py +0 -0
  16. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_acoustic_chirp_spl_bt.py +0 -0
  17. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_acoustic_dbspl.py +0 -0
  18. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_acoustic_energy_decay_bt.py +0 -0
  19. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_coherent_averaging.py +0 -0
  20. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_cross_correlation.py +0 -0
  21. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_freq_response_with_mask.py +0 -0
  22. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_pinknoise.py +0 -0
  23. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/PyQa40x_thdn.py +0 -0
  24. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/mask_freq.txt +0 -0
  25. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/LibTest/mask_phase.txt +0 -0
  26. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/MANIFEST.in +0 -0
  27. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/README.md +0 -0
  28. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/_ci/is_dev_version.sh +0 -0
  29. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/pyproject.toml +0 -0
  30. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/requirements-dev.txt +0 -0
  31. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/requirements-test.txt +0 -0
  32. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/requirements.txt +0 -0
  33. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/setup.cfg +0 -0
  34. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/__init__.py +0 -0
  35. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/analyzer_params.py +0 -0
  36. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/bluetooth.py +0 -0
  37. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/control.py +0 -0
  38. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/cross_correlation.py +0 -0
  39. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/fft_processor.py +0 -0
  40. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/freq_series_plotter.py +0 -0
  41. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/helpers.py +0 -0
  42. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/math_chirp.py +0 -0
  43. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/math_energy.py +0 -0
  44. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/math_general.py +0 -0
  45. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/math_sines.py +0 -0
  46. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/math_windows.py +0 -0
  47. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/registers.py +0 -0
  48. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/series_plotter.py +0 -0
  49. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/sig_proc.py +0 -0
  50. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/wave.py +0 -0
  51. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/wave_chirp.py +0 -0
  52. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x/wave_sine.py +0 -0
  53. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x.egg-info/PKG-INFO +0 -0
  54. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x.egg-info/SOURCES.txt +0 -0
  55. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x.egg-info/dependency_links.txt +0 -0
  56. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x.egg-info/requires.txt +0 -0
  57. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x.egg-info/top_level.txt +0 -0
  58. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x_i2c.egg-info/SOURCES.txt +0 -0
  59. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x_i2c.egg-info/dependency_links.txt +0 -0
  60. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x_i2c.egg-info/requires.txt +0 -0
  61. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x_i2c.egg-info/scm_file_list.json +0 -0
  62. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/src/PyQa40x_i2c.egg-info/top_level.txt +0 -0
  63. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/tests/__init__.py +0 -0
  64. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/tests/test_template.py +0 -0
  65. {pyqa40x_i2c-0.3.0 → pyqa40x_i2c-0.3.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyQa40x-i2c
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: A Python library for the QA40x audio analyser (int2code fork)
5
5
  Maintainer-email: Hubert Stepniewski <hubert.stepniewski@int2code.com>
6
6
  License: MIT License
@@ -1,3 +1,11 @@
1
+ ### 0.3.2
2
+
3
+ [PATCH] Add modifying max input level
4
+
5
+ ### 0.3.1
6
+
7
+ [PATCH] Fix Stream.write() - ensure transfer queues not empty.
8
+
1
9
  ### 0.3.0
2
10
 
3
11
  [MINOR] `Analyzer.init()` accepts `usb_serial` to open a specific QA402/QA403 by its USB serial number, so a PC with several analyzers can drive a chosen one. The argument is last and optional; without it the first analyzer found is opened, exactly as before.
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.3.0'
22
- __version_tuple__ = version_tuple = (0, 3, 0)
21
+ __version__ = version = '0.3.2'
22
+ __version_tuple__ = version_tuple = (0, 3, 2)
23
23
 
24
- __commit_id__ = commit_id = 'geab2d8779'
24
+ __commit_id__ = commit_id = 'g8ba62af0c'
@@ -177,6 +177,27 @@ class Analyzer:
177
177
 
178
178
  return self.params
179
179
 
180
+ def set_max_input_level(self, max_input_level: int) -> None:
181
+ """
182
+ Set the input attenuator to `max_input_level` dBV.
183
+
184
+ Args:
185
+ max_input_level (int): Maximum input level in dBV. Valid values are 0, 6, 12, 18, 24, 30, 36, 42.
186
+
187
+ Raises:
188
+ ValueError: If `max_input_level` is not a valid level.
189
+ RuntimeError: If a capture is running.
190
+ """
191
+ if max_input_level not in self.control.input2reg:
192
+ raise ValueError(
193
+ f"Invalid max input level {max_input_level} dBV; valid values are "
194
+ f"{sorted(self.control.input2reg)}."
195
+ )
196
+ if self._capturing:
197
+ raise RuntimeError("Cannot change the max input level while capturing.")
198
+ self.control.set_input(max_input_level)
199
+ self.params.max_input_level = max_input_level
200
+
180
201
  def cleanup(self):
181
202
  """
182
203
  Releases the USB device interface and closes the context.
@@ -193,22 +193,34 @@ class Stream:
193
193
 
194
194
  def write(self, buffer: bytes) -> None:
195
195
  """Submit one DAC playback buffer and one matching ADC read transfer."""
196
- with self._transfer_lock:
197
- if not self.running:
198
- raise RuntimeError(
199
- "Stream is not running; call start() first.")
200
- dac = self.device.getTransfer()
201
- dac.setBulk(self.endpoint_write, buffer, self.transfer_helper,
202
- self._epoch, self.TRANSFER_TIMEOUT_MS)
203
- dac.submit()
204
- self._pending_transfers.add(dac)
205
- read = self.device.getTransfer()
206
- read.setBulk(self.endpoint_read, len(buffer), self.transfer_helper,
207
- self._epoch, self.TRANSFER_TIMEOUT_MS)
208
- read.submit()
209
- self._pending_transfers.add(read)
196
+ dac = self.device.getTransfer()
197
+ read = self.device.getTransfer()
198
+ # Enqueue before submit: a transfer can complete, and its callback
199
+ # drain the queue, before submit() returns.
210
200
  self.dacQueue.put(dac)
211
201
  self.adcQueue.put(read)
202
+ dac_submitted = read_submitted = False
203
+ with self._transfer_lock:
204
+ try:
205
+ if not self.running:
206
+ raise RuntimeError(
207
+ "Stream is not running; call start() first.")
208
+ dac.setBulk(self.endpoint_write, buffer, self.transfer_helper,
209
+ self._epoch, self.TRANSFER_TIMEOUT_MS)
210
+ dac.submit()
211
+ dac_submitted = True
212
+ self._pending_transfers.add(dac)
213
+ read.setBulk(self.endpoint_read, len(buffer), self.transfer_helper,
214
+ self._epoch, self.TRANSFER_TIMEOUT_MS)
215
+ read.submit()
216
+ read_submitted = True
217
+ self._pending_transfers.add(read)
218
+ except Exception:
219
+ if not dac_submitted:
220
+ self.dacQueue.get_nowait()
221
+ if not read_submitted:
222
+ self.adcQueue.get_nowait()
223
+ raise
212
224
 
213
225
  def write_zeros(self, chunk_bytes: int = DEFAULT_TRANSFER_BYTES) -> None:
214
226
  """Feed the ADC pipeline with a zero DAC buffer (continuous capture)."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyQa40x-i2c
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: A Python library for the QA40x audio analyser (int2code fork)
5
5
  Maintainer-email: Hubert Stepniewski <hubert.stepniewski@int2code.com>
6
6
  License: MIT License
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.3.2",
3
+ "distance": 0,
4
+ "node": "g8ba62af0c0b31ab8c1f821380de14489ffd93e86",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-16"
8
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.3.0",
3
- "distance": 0,
4
- "node": "geab2d87790fb78dcedbb2918bc95d4b682060108",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-08-24"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes