クラス I2CTarget -- I2C ターゲットデバイス
I2Cターゲットとは、I2Cバスに接続され、I2Cコントローラーから制御されるデバイスのことです。その形態はさまざまです。 machine.I2CTarget クラスを使えば、メモリ/レジスタデバイスとして動作させることも、(ポートが対応していれば)コールバックを使って任意のI2Cデバイスとして動作させることもできます。
メモリデバイスとして使う場合の例を次に示します:
from machine import I2CTarget
# I2Cターゲット用のバックエンドメモリを作成。
mem = bytearray(8)
# I2Cターゲットを作成。ポートによっては、利用するペリフェラルやピンを選択
# するために追加のパラメータが必要になる場合があります。
i2c = I2CTarget(addr=67, mem=mem)
# この時点で、I2Cコントローラーは `mem` への読み書きが可能になります。
...
# I2Cターゲットを無効化(初期化解除)します。
i2c.deinit()
一部のポートでは I2CTarget コンストラクタに id や scl / sda ピンを指定する必要があります。これは、ハードウェアI2Cインスタンスと接続先のピンを選択するためです。
メモリデバイスとして構成した場合、イベントを受け取るように登録することもできます。たとえば、メモリが読み書きされたタイミングで通知を受け取る方法は次のとおりです:
from machine import I2CTarget
# I2C イベントのための IRQ ハンドラーを定義。
def irq_handler(i2c_target):
flags = i2c_target.irq().flags()
if flags & I2CTarget.IRQ_END_READ:
print("controller read target at addr", i2c_target.memaddr)
if flags & I2CTarget.IRQ_END_WRITE:
print("controller wrote target at addr", i2c_target.memaddr)
# I2C ターゲットを作成し、デフォルトのイベントを受け取るよう登録。
mem = bytearray(8)
i2c = I2CTarget(addr=67, mem=mem)
i2c.irq(irq_handler)
より複雑なI2Cデバイスは、すべてのイベントを利用して実装することもできます。たとえば、イベントが発生したときに、その生のイベント内容を確認する方法は次のとおりです:
from machine import I2CTarget
# イベントIDを表示し、読取り/書込み要求に応答するIRQハンドラを定義。
def irq_handler(i2c_target, buf=bytearray(1)):
flags = i2c_target.irq().flags()
print(flags)
if flags & I2CTarget.IRQ_READ_REQ:
i2c_target.write(buf)
if flags & I2CTarget.IRQ_WRITE_REQ:
i2c_target.readinto(buf)
# Create the I2C target and register to receive all events.
# I2Cターゲットを作成し、すべてのイベントを受け取るよう登録。
i2c = I2CTarget(addr=67)
all_triggers = (
I2CTarget.IRQ_ADDR_MATCH_READ
| I2CTarget.IRQ_ADDR_MATCH_WRITE
| I2CTarget.IRQ_READ_REQ
| I2CTarget.IRQ_WRITE_REQ
| I2CTarget.IRQ_END_READ
| I2CTarget.IRQ_END_WRITE
)
i2c.irq(irq_handler, trigger=all_triggers, hard=True)
コンストラクタ
- class machine.I2CTarget(id, addr, *, addrsize=7, mem=None, mem_addrsize=8, scl=None, sda=None)
次のパラメータを使って、新しい I2CTarget オブジェクトを生成して返します:
id は使用するI2Cペリフェラルを識別します。指定できる値は、ポートやボードによって異なります。一部のポートではデフォルトが設定されており、その場合このパラメータは省略可能です。
addr はターゲットのI2Cアドレスです。
addrsize はI2Cターゲットアドレスのビット数です。指定可能な値は 7 と 10 です。
mem は書出し可能なバッファプロトコルを持つオブジェクトです。これを指定しない場合はバックエンドメモリが存在せず、データの読み書きは
I2CTarget.readinto()とI2CTarget.write()メソッドで行う必要があります。mem_addrsize はメモリアドレスのビット数です。指定可能な値は 0, 8, 16, 24, 32 です。
scl はSCL用に使うピンを指定するピンオブジェクトです。
sda はSDA用に使うピンを指定するピンオブジェクトです。
ポートやボードによっては、このコンストラクタで指定する scl と sda のデフォルト値を持っていることに注意してください。 scl と sda が固定で変更できないこともあります。
一般的なメソッド
- I2CTarget.deinit()
I2Cターゲットをします。このメソッドを呼び出すと、ハードウェアはI2Cバス上での要求に応答しなくなり、その他のメソッドも呼び出せなくなります。
- I2CTarget.readinto(buf)
I2Cコントローラーから書き出されている保留中のデータを指定したバッファに読み込みます。戻り値は読み込んだバイト数です。
- I2CTarget.write(buf)
指定したバッファのデータを、I2Cコントローラーからの読込み要求に応じて送信します。戻り値は書き出したバイト数です。多くのポートでは、このメソッドで一度に書き出せるのは1バイトのみです。
- I2CTarget.irq(handler=None, trigger=IRQ_END_READ | IRQ_END_WRITE, hard=False)
イベント発生時に呼び出されるIRQ ハンドラ を設定します。指定可能なイベントは次の定数で定義されており、これらを ビット和演算子で組み合わせて trigger 引数に渡すことができます。
IRQ_ADDR_MATCH_READは、読込みトランザクションのコントローラーにターゲットが認識されたことを示します。IRQ_ADDR_MATCH_WRITEは、書出しトランザクションのコントローラーにターゲットが認識されたことを示します。IRQ_READ_REQは、コントローラーがデータを要求しており、この要求に応えるためにI2CTarget.writeを呼び出して、コントローラーに返すデータを指定する必要があることを示します。IRQ_WRITE_REQは、コントローラーがデータを書き出しており、そのデータを読み込むためにI2CTarget.readintoを呼び出す必要があることを示します。IRQ_END_READは、コントローラーが読込みトランザクションを終了したことを示します。IRQ_END_WRITEは、コントローラーが書出しトランザクションを終了したことを示します。
すべてのトリガーがすべてのポートで利用できるわけではありません。利用するポートで該当する定数が定義されている場合のみ、そのイベントは利用可能です。
次の制約に注意してください:
IRQ_ADDR_MATCH_READ,IRQ_ADDR_MATCH_WRITE,IRQ_READ_REQ,IRQ_WRITE_REQは、ハードIRQコールバック(hard 引数にTrueを指定)で処理する必要があります。これは、これらのイベントが非常に厳しいタイミング制約を持ち、通常はハードウェアイベントと同期して即座に処理する必要があるためです。IRQ_END_READとIRQ_END_WRITEは、ソフトIRQコールバックでもハードIRQコールバックでも処理可能です。ただし、すべてのイベントは同じハンドラに登録する必要があるため、もし1つでもハードIRQが必要なイベントがある場合、すべてのイベントをハードIRQとして登録しなければなりません。コンストラクタでメモリバッファを指定している場合、メモリアドレスを書き出すトランザクションでは
IRQ_END_WRITEは発行されません。これはIRQ_END_READとIRQ_END_WRITEがソフトIRQコールバックとして正しく動作するようにするためで、ソフトIRQの場合、IRQハンドラは実際のハードウェアイベントからかなり遅れて呼び出されることがあるためです。
- I2CTarget.memaddr
I2Cコントローラーによって最後に選択されたメモリアドレスの整数値(コンストラクタで
memを指定した場合にのみ有効)。