Skip to content

Commit

Permalink
aop: Support Ambient Light Sensor (ALS) endpoint
Browse files Browse the repository at this point in the history
```
[syslog] * [ALSCT720.cpp:708]setSensorEnabled - Enabling the sensor.
> 02:0x5000000000002d (TYPE=0x5, INDEX=0x2d)
< 24:0x85000000000000
[als] Container:
    unk0 = 0xEC
    sequence = 0
    timestamp = 0x00000000028415F3
    red = 10
    green = 12
    blue = 6
    clear = 28
    lux_maybe = 0x40AF2579
    unk_zero = 0
    status = 3
    gain = 256
    unk3 = 42
    unk4 = 188
    unk5 = 17811
    integration_time = 197380
```

Signed-off-by: Eileen Yoon <[email protected]>
  • Loading branch information
eiln committed Jan 21, 2024
1 parent 6a360fe commit bda9b37
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 7 deletions.
88 changes: 88 additions & 0 deletions proxyclient/experiments/aop_als.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
import sys, pathlib
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))

import struct
from construct import *

from m1n1.setup import *
from m1n1.hw.dart import DART
from m1n1.fw.aop.client import AOPClient
from m1n1.fw.aop.ipc import *

# aop nodes have no clocks described in adt for j293. it does it itself
p.pmgr_adt_clocks_enable("/arm-io/aop")
p.pmgr_adt_clocks_enable("/arm-io/dart-aop")

dart = DART.from_adt(u, "/arm-io/dart-aop",
iova_range=(u.adt["/arm-io/dart-aop"].vm_base, 0x1000000000))
dart.initialize()

aop = AOPClient(u, "/arm-io/aop", dart)
aop.update_bootargs({
'p0CE': 0x20000,
'laCn': 0x0,
'tPOA': 0x1,
"gila": 0x80,
})
aop.verbose = 4

p.dapf_init_all()
aop.asc.OUTBOX_CTRL.val = 0x20001 # (FIFOCNT=0x0, OVERFLOW=0, EMPTY=1, FULL=0, RPTR=0x0, WPTR=0x0, ENABLE=1)

aop.start()
for epno in [0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x27, 0x28]:
aop.start_ep(epno)
timeout = 5
while (not aop.als.ready) and timeout:
aop.work_for(0.1)
timeout -= 1
if not timeout:
raise Exception("Timed out waiting on als endpoint")
print("Finished boot")
alsep = aop.als
alsep.VERBOSE = True

def start():
ret = alsep.roundtrip(GetProperty(key=AOPPropKey.MANUFACTURER))
print(ret.rets.value.decode("ascii")) # FireFish2

ret = alsep.roundtrip(ALSSetPropertyVerbosity(level=0xffffffff))
# [syslog] * [ALSAOPDriver.cpp:267]setProperty Setting log level = -1

dump = """
00000000 09 00 00 10 00 00 00 00 02 24 00 00 00 00 00 00 |.........$......|
00000010 00 00 00 00 00 00 00 00 99 00 00 00 02 10 04 00 |................|
00000020 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |$...............|
00000030 00 00 00 00 0b 00 00 00 01 02 00 00 00 ad ab 0a |................|
00000040 00 01 91 00 9a 59 fa 00 64 00 64 00 08 08 08 04 |.....Y..d.d.....|
00000050 09 63 eb ff ff d4 0e 00 00 c7 ce ff ff 23 2e 00 |.c...........#..|
00000060 00 a2 08 cd 14 d6 5f 77 05 00 00 00 00 00 02 00 |......_w........|
00000070 80 aa 7e 53 7f 10 84 d9 7e 68 7f 68 7f b3 7f f1 |..~S....~h.h....|
00000080 7d 00 00 00 00 00 03 5b 7e 56 7e 00 80 ca 83 e0 |}......[~V~.....|
00000090 7e 79 7f 00 80 8d 80 f1 7f 00 00 00 00 00 02 f3 |~y..............|
000000a0 7c 00 80 38 7f 88 83 0b 7f 05 7f b9 7f b9 7f 0f ||..8............|
000000b0 7e 00 00 00 00 00 06 75 7e 38 7f 69 7f bf 83 f2 |~......u~8.i....|
000000c0 7e 16 7f 4e 7f 33 7f 1f 7d |~..N.3..} |
"""
ret = alsep.roundtrip(ALSSetPropertyCalibration(value=chexundump(dump)[0x38:]))
# [syslog] * [ALSCT720.cpp:1138]loadALSCalibrationData: ALS sensor is calibrated

ret = alsep.roundtrip(ALSSetPropertyInterval(interval=200000))
# [syslog] * [ALSCT720.cpp:690]configureSensor - Configure sensor with gain 8 and integration time 197380
# [syslog] * [ALSCT720.cpp:708]setSensorEnabled - Enabling the sensor.

if 0: # test that on/off works
aop.work_for(0.5)
ret = alsep.roundtrip(ALSSetPropertyInterval(interval=0))
# [syslog] * [ALSCT720.cpp:598]setProperty: set report interval 0, _wakeHintMode = 0
# [syslog] * [ALSCT720.cpp:735]setSensorEnabled - Disabling the sensor.
ret = alsep.roundtrip(ALSSetPropertyInterval(interval=200000))
while True:
aop.work()

try:
start()
except KeyboardInterrupt:
pass
5 changes: 5 additions & 0 deletions proxyclient/m1n1/fw/aop/aopep.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ def start_queues(self):
class AOPALSEndpoint(AOPEPICEndpoint): # als.hint
SHORT = "als"

@report_handler(0xc4, ALSLuxReport)
def handle_lux(self, hdr, sub, fd, rep):
self.log(rep)
return True

class AOPWakehintEndpoint(AOPEPICEndpoint): # wakehint
SHORT = "wakehint"

Expand Down
103 changes: 96 additions & 7 deletions proxyclient/m1n1/fw/aop/ipc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
from m1n1.utils import FourCC, chexdump
from m1n1.constructutils import *

class AOPAudioPropKey(IntEnum):
class AOPPropKey(IntEnum):
IS_READY = 0x01
UNK_11 = 0x11
MANUFACTURER = 0x0f # wtf is a firefish2?
CHIP_ID = 0x11
PLACEMENT = 0x1e
UNK_21 = 0x21
ORIENTATION = 0x2e
LOCATION_ID = 0x30
PRODUCT_ID2 = 0x3f
SERIAL_NO = 0x3e
VENDOR_ID = 0x5a
PRODUCT_ID = 0x5b
Expand Down Expand Up @@ -48,9 +50,11 @@ def dump(self, logger=print):
def read_resp(self, f):
self.rets = self.RETS.parse_stream(f)

CALLTYPES = []
CALLTYPES = {}
def reg_calltype(calltype):
CALLTYPES.append(calltype)
if (calltype.TYPE in CALLTYPES):
raise ValueError("duplicate type 0x%x" % (calltype.TYPE))
CALLTYPES[calltype.TYPE] = calltype
return calltype

@reg_calltype
Expand All @@ -60,7 +64,7 @@ class GetHIDDescriptor(EPICCall):
"blank" / Const(0x0, Int32ul),
)
RETS = Struct(
"retcode" / Default(Hex(Int32ul), 0),
"retcode" / Const(0x0, Hex(Int32ul)),
"descriptor" / HexDump(GreedyBytes),
)

Expand All @@ -69,13 +73,97 @@ class GetProperty(EPICCall):
TYPE = 0xa
ARGS = Struct(
"blank" / Const(0x0, Int32ul),
"key" / Enum(Int32ul, AOPAudioPropKey),
"key" / Enum(Int32ul, AOPPropKey),
)
RETS = Struct(
#"blank" / Const(0x0, Int32ul),
#"retcode" / Const(0x0, Int32ul),
"value" / GreedyBytes,
)

class ALSPropertyKey(IntEnum):
INTERVAL = 0x00
CALIBRATION = 0x0b
MODE = 0xd7
VERBOSITY = 0xe1

@reg_calltype
class ALSSetProperty(EPICCall):
TYPE = 0x4
SUBCLASSES = {}

@classmethod
def subclass(cls, cls2):
cls.SUBCLASSES[int(cls2.SUBTYPE)] = cls2
return cls2

@ALSSetProperty.subclass
class ALSSetPropertyVerbosity(ALSSetProperty):
SUBTYPE = ALSPropertyKey.VERBOSITY
ARGS = Struct(
"blank" / Const(0x0, Int32ul),
"key" / Default(Hex(Int32ul), ALSPropertyKey.VERBOSITY),
"level" / Hex(Int32ul),
)
RETS = Struct(
"retcode" / Const(0x0, Int32ul),
"value" / GreedyBytes,
)

@ALSSetProperty.subclass
class ALSSetPropertyMode(ALSSetProperty):
SUBTYPE = ALSPropertyKey.MODE
ARGS = Struct(
"blank" / Const(0x0, Int32ul),
"key" / Default(Hex(Int32ul), ALSPropertyKey.MODE),
"mode" / Int32ul,
)
RETS = Struct(
"retcode" / Const(0x0, Int32ul),
"value" / GreedyBytes,
)

@ALSSetProperty.subclass
class ALSSetPropertyCalibration(ALSSetProperty):
SUBTYPE = ALSPropertyKey.CALIBRATION
ARGS = Struct(
"blank" / Const(0x0, Int32ul),
"key" / Default(Hex(Int32ul), ALSPropertyKey.CALIBRATION),
"value" / GreedyBytes,
)
RETS = Struct(
"retcode" / Const(0xE00002BC, Hex(Int32ul)),
)

@ALSSetProperty.subclass
class ALSSetPropertyInterval(ALSSetProperty):
SUBTYPE = ALSPropertyKey.INTERVAL
ARGS = Struct(
"blank" / Const(0x0, Int32ul),
"key" / Default(Hex(Int32ul), ALSPropertyKey.INTERVAL),
"interval" / Int32ul,
)
RETS = Struct(
"retcode" / Const(0x0, Int32ul),
)

ALSLuxReport = Struct(
"unk0" / Const(0xec, Hex(Int8ul)),
"sequence" / Int32ul,
"timestamp" / Hex(Int64ul),
"red" / Int32ul,
"green" / Int32ul,
"blue" / Int32ul,
"clear" / Int32ul,
"lux_maybe" / Hex(Int32ul),
"unk_zero" / Int32ul, # 0
"status" / Int32ul, # 3
"gain" / Int16ul,
"unk3" / Int8ul,
"unk4" / Int8ul,
"unk5" / Int16ul,
"integration_time" / Int32ul,
)

@reg_calltype
class WrappedCall(EPICCall):
SUBCLASSES = {}
Expand Down Expand Up @@ -304,6 +392,7 @@ def _args_fixup(self):

@reg_calltype
class IndirectCall(EPICCall):
TYPE = 0xffff
ARGS = EPICCmd
RETS = EPICCmd

Expand Down

0 comments on commit bda9b37

Please sign in to comment.