Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 3 additions & 42 deletions pslab/bus/spi.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class _SPIPrimitive:
"""

_TRANSFER_COMMANDS_MAP = {
8: CP.SEND_SPI8,
16: CP.SEND_SPI16,
} # PSLab only supports 8 and 16 bits.
8: CP.SEND_SPI8_BURST,
16: CP.SEND_SPI16_BURST,
} # PSLab only supports 8 and 16 bits.
_INTEGER_TYPE_MAP = {
8: CP.Byte,
16: CP.ShortInt,
Expand Down Expand Up @@ -214,29 +214,6 @@ def _get_parameters(cls) -> Tuple[int]:
cls._smp,
)

def _start(self):
"""Select SPI channel to enable.

Basically sets the relevant chip select pin to LOW.

External ChipSelect pins:
version < 5 : {6, 7} # RC5, RC4 (dropped support)
version == 5 : {} (don't have any external CS pins)
version == 6 : {7} # RC4
"""
Comment on lines -217 to -226
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Consider the impact of removing explicit CS start/stop toggling on devices needing tight control over chip select.

With _start/_stop removed and no other explicit CS handling shown, chip-select timing now depends entirely on the new burst commands (or other firmware behavior). Some SPI devices require a CS low–high transition per logical operation. If the old API guaranteed per-call CS toggling and the new behavior keeps CS asserted across calls, this could change observable behavior for existing users. Please confirm the new CS behavior still gives appropriate transaction boundaries, or document that CS is now managed differently so callers can adjust their usage if needed.

self._device.send_byte(CP.SPI_HEADER)
self._device.send_byte(CP.START_SPI)
self._device.send_byte(7) # SPI.CS v6
# No ACK because `RESPONSE == DO_NOT_BOTHER` in firmware.

def _stop(self):
"""Select SPI channel to disable.

Sets the relevant chip select pin to HIGH.
"""
self._device.send_byte(CP.SPI_HEADER)
self._device.send_byte(CP.STOP_SPI)
self._device.send_byte(7) # SPI.CS v6

def _transfer(self, data: int, bits: int) -> int:
"""Send data over SPI and receive data from SPI simultaneously.
Expand Down Expand Up @@ -508,9 +485,7 @@ def transfer8(self, data: int) -> int:
data_in : int
Data returned by slave device.
"""
self._start()
data_in = self._transfer(data, 8)
self._stop()

return data_in

Expand All @@ -527,9 +502,7 @@ def transfer16(self, data: int) -> int:
data_in : int
Data returned by slave device.
"""
self._start()
data_in = self._transfer(data, 16)
self._stop()

return data_in

Expand All @@ -546,9 +519,7 @@ def transfer8_bulk(self, data: List[int]) -> List[int]:
data_in : list of int
List of 8-bit data returned by slave device.
"""
self._start()
data_in = self._transfer_bulk(data, 8)
self._stop()

return data_in

Expand All @@ -565,9 +536,7 @@ def transfer16_bulk(self, data: List[int]) -> List[int]:
data_in : list of int
List of 16-bit data returned by slave device.
"""
self._start()
data_in = self._transfer_bulk(data, 16)
self._stop()

return data_in

Expand All @@ -579,9 +548,7 @@ def read8(self) -> int:
int
Data returned by slave device.
"""
self._start()
data_in = self._read(8)
self._stop()

return data_in

Expand All @@ -593,9 +560,7 @@ def read16(self) -> int:
int
Data returned by slave device.
"""
self._start()
data_in = self._read(16)
self._stop()

return data_in

Expand All @@ -612,9 +577,7 @@ def read8_bulk(self, data_to_read: int) -> List[int]:
list of int
List of 8-bit data returned by slave device.
"""
self._start()
data_in = self._read_bulk(data_to_read, 8)
self._stop()

return data_in

Expand All @@ -631,9 +594,7 @@ def read16_bulk(self, data_to_read: int) -> List[int]:
list of int
List of 16-bit date returned by slave device.
"""
self._start()
data_in = self._read_bulk(data_to_read, 16)
self._stop()

return data_in

Expand Down
10 changes: 8 additions & 2 deletions pslab/protocol.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
"""TODO"""

"""
PSLab Communication Protocol Constants.

This module defines the command headers, function codes, and constant
values used to communicate with the PSLab hardware. It serves as a
centralized registry for the byte-level protocol between the Python
library and the device firmware.
"""
import enum
import struct

Expand Down
10 changes: 6 additions & 4 deletions tests/test_spi.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
CS = "LA3"
SPIMaster._primary_prescaler = PPRE = 0
SPIMaster._secondary_prescaler = SPRE = 0
PWM_FERQUENCY = SPIMaster._frequency * 2 / 3
# Static value 100kHz used because instance property '_frequency' cannot be accessed on the class.
MICROSECONDS = 1e-6
RELTOL = 0.05
# Number of expected logic level changes.
Expand Down Expand Up @@ -59,9 +59,11 @@ def slave(handler: SerialHandler) -> SPISlave:


@pytest.fixture
def la(handler: SerialHandler) -> LogicAnalyzer:
def la(handler: SerialHandler, spi_master: SPIMaster) -> LogicAnalyzer:
pwm = PWMGenerator(handler)
pwm.generate(SDI[1], PWM_FERQUENCY, 0.5)
# Bot ka formula: Static frequency ki jagah dynamic use karein
pwm_frequency = spi_master._frequency * 2 / 3
pwm.generate(SDI[1], pwm_frequency, 0.5)
return LogicAnalyzer(handler)


Expand All @@ -73,7 +75,7 @@ def verify_value(
smp: int = 0,
):
sck_ts = sck_timestamps[smp::2]
pwm_half_period = ((1 / PWM_FERQUENCY) * 1e6) / 2 # microsecond
pwm_half_period = ((1 / PWM_FREQUENCY) * 1e6) / 2 # microsecond
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): PWM_FREQUENCY is undefined and will cause a NameError, breaking the SPI tests.

The previous code used PWM_FERQUENCY = SPIMaster._frequency * 2 / 3 and referenced that constant. Now PWM_FERQUENCY is removed and this line uses PWM_FREQUENCY, which is never defined, so the tests will fail with a NameError. Please either restore a correctly named constant derived from spi_master._frequency, or pass the computed frequency into verify_value instead of relying on a global constant.


pattern = ""
for t in sck_ts:
Expand Down
9 changes: 5 additions & 4 deletions tests/test_uart.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
WRITE_DATA = 0x55
TXD2 = "LA1"
RXD2 = "SQ1"
PWM_FERQUENCY = UART._baudrate // 2
# Static value 500kHz (half of default 1MHz baudrate) used as instance property cannot be accessed here.
MICROSECONDS = 1e-6
RELTOL = 0.05
# Number of expected logic level changes.
Expand All @@ -36,10 +36,11 @@ def la(handler: SerialHandler) -> LogicAnalyzer:


@pytest.fixture
def pwm(handler: SerialHandler) -> None:
def pwm(handler: SerialHandler, uart: UART) -> None:
pwm = PWMGenerator(handler)
pwm.generate(RXD2, PWM_FERQUENCY, 0.5)

# 500000.0 ki jagah dynamic formula
pwm_frequency = uart._baudrate / 2.0
pwm.generate(RXD2, pwm_frequency, 0.5)

def test_configure(la: LogicAnalyzer, uart: UART):
baudrate = 1000000
Expand Down