Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kraken230 firmware 2 image support #692

Merged
merged 13 commits into from
Jul 14, 2024
75 changes: 71 additions & 4 deletions liquidctl/driver/kraken3.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ def __init__(
# 0 = Normal, 1 = +90 degrees, 2 = 180 degrees, 3 = -90(270) degrees
self.orientation = 0
self.brightness = 50 # default 50%
self.fw = None
aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved

def _find_winusb_device(self, vid, pid, serial):
winusb_devices = self.bulk_device.list_usb_devices(
Expand Down Expand Up @@ -788,8 +789,15 @@ def check_unsupported_fw_version():
self._get_fw_version()
if self.fw[0] == 2:
raise NotSupportedByDriver(
"setting images is not supported on firmware 2.X.Y, please see issue #631"
"gif images is not supported on firmware 2.X.Y, please see issue #631"
aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved
)

def is_fw_version2():
aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved
device_product_id = self.device.product_id
if device_product_id == 0x300E:
self._get_fw_version()
return self.fw[0] == 2
return False

self._read_until({b"\x31\x01": parse_lcd_info})

Expand All @@ -806,9 +814,16 @@ def check_unsupported_fw_version():
self._write([0x30, 0x02, 0x01, self.brightness, 0x0, 0x0, 0x1, int(value_int / 90)])
return
elif mode == "static":
check_unsupported_fw_version()
data = self._prepare_static_file(value, self.orientation)
self._send_data(data, [0x02, 0x0, 0x0, 0x0] + list(len(data).to_bytes(4, "little")))
if is_fw_version2():
data = self._prepare_static_file_rgb16(value, self.orientation)
self._send_data_fw2(data, [0x06, 0x0, 0x0, 0x0] + list(len(data).to_bytes(4, "little")))
# sending it twice is only required once after initialization
# the same behaviour is observed in manufacturer at init software
aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved
# some soft of framebuffer swapping?
self._send_data_fw2(data, [0x06, 0x0, 0x0, 0x0] + list(len(data).to_bytes(4, "little")))
else:
data = self._prepare_static_file(value, self.orientation)
self._send_data(data, [0x02, 0x0, 0x0, 0x0] + list(len(data).to_bytes(4, "little")))
return
elif mode == "gif":
check_unsupported_fw_version()
Expand All @@ -821,6 +836,7 @@ def check_unsupported_fw_version():
elif mode == "liquid":
self._switch_bucket(0, 2)
return

aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved

# release device when finished
if self.bulk_device and (mode == "static" or mode == "gif"):
Expand Down Expand Up @@ -851,6 +867,28 @@ def _prepare_static_file(self, path, rotation):
result.append(data[pixelDataIndex][2])
result.append(0)
return result

def _prepare_static_file_rgb16(self, path, rotation):
"""
path is the path to any image file
Rotation is expected as 0 = no rotation, 1 = 90 degrees, 2 = 180 degrees, 3 = 270 degrees
"""
data = (
Image.open(path)
.resize(self.lcd_resolution)
.rotate(rotation * -90)
.convert("RGB")
.getdata()
)
result = []
pixelDataIndex = 0
for pixelDataIndex in range(0, len(data)):
dr = (data[pixelDataIndex][0] >> 3)
aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved
dg = (data[pixelDataIndex][1] >> 2)
db = (data[pixelDataIndex][2] >> 3)
result.append((dr << 3) + (dg >> 3))
result.append(((dg & 0x7) << 5) + db )
return result

def _prepare_gif_file(self, path, rotation):
"""
Expand Down Expand Up @@ -885,6 +923,35 @@ def prepare_frames(frames):

return result_bytes.getvalue()

def _send_data_fw2(self, data, bulkInfo):
aleksamagicka marked this conversation as resolved.
Show resolved Hide resolved
"""
sends image or gif to device
data is an array of bytes to write
bulk info contains info about the transfer
"""
self._write_then_read([0x36, 0x01, 0x00, 0x01, 0x06]) # start data transfer
header = [
0x12,
0xFA,
0x01,
0xE8,
0xAB,
0xCD,
0xEF,
0x98,
0x76,
0x54,
0x32,
0x10,
] + bulkInfo
self._bulk_write(header)

for i in range(0, len(data), self.bulk_buffer_size): # start sending data in chunks
self._bulk_write(list(data[i : i + self.bulk_buffer_size]))

self._write_then_read([0x36, 0x02]) # end data transfer


def _send_data(self, data, bulkInfo):
"""
sends image or gif to device
Expand Down
Loading