Adds the second panel model alongside V1 (800x480, 7.3"). V2 is 1200x1600 panel-native (tall) — the inverse aspect ratio means its "natural" orientation is portrait, not landscape: - DeviceModel::nativeOrientation() — V1 returns Landscape, V2 returns Portrait. Render rotates the source image 90 CCW only when the user's orientation differs from the panel's native, so the .bin stays panel-native scan order without per-model branches. - DeviceModel::panelId() / fromPanelId() — string mapping for the firmware's X-Panel-Id header (matches -DPANEL_ID build flag). - DeviceImageController: on every poll, if X-Panel-Id maps to a known model and differs from the device's current model, auto-correct. New Devices are created with the V1 default, so a freshly-claimed 13.3" unit needs this correction before the first image render produces a wrong-dimension .bin the firmware would reject. 8 new DeviceModel unit tests, 3 new controller tests cover the header-correction behaviour (different, same, unknown panel-id). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,10 @@ use PHPUnit\Framework\TestCase;
|
||||
/**
|
||||
* width()/height() must follow orientation, but nativeWidth()/nativeHeight()
|
||||
* are the EPD's hardware scan dimensions and must NOT depend on orientation
|
||||
* (the renderer pre-rotates portrait images and streams raw bytes).
|
||||
* (the renderer pre-rotates non-native images and streams raw bytes).
|
||||
*
|
||||
* V1 panel is wide-native (800×480 landscape); V2 is tall-native (1200×1600
|
||||
* portrait). nativeOrientation() decides whether rendering rotates.
|
||||
*/
|
||||
class DeviceModelTest extends TestCase
|
||||
{
|
||||
@@ -27,12 +30,54 @@ class DeviceModelTest extends TestCase
|
||||
$this->assertSame(800, DeviceModel::V1->height(Orientation::Portrait));
|
||||
}
|
||||
|
||||
public function test_native_dimensions_ignore_orientation(): void
|
||||
public function test_v1_native_dimensions_ignore_orientation(): void
|
||||
{
|
||||
// The firmware streams 800x480 EPD-native rows regardless of how the
|
||||
// photo was framed; renderer rotates the input photo, then writes in
|
||||
// EPD scan order.
|
||||
$this->assertSame(800, DeviceModel::V1->nativeWidth());
|
||||
$this->assertSame(480, DeviceModel::V1->nativeHeight());
|
||||
}
|
||||
|
||||
public function test_v1_native_orientation_is_landscape(): void
|
||||
{
|
||||
$this->assertSame(Orientation::Landscape, DeviceModel::V1->nativeOrientation());
|
||||
}
|
||||
|
||||
public function test_v2_portrait_dimensions_are_1200x1600(): void
|
||||
{
|
||||
$this->assertSame(1200, DeviceModel::V2->width(Orientation::Portrait));
|
||||
$this->assertSame(1600, DeviceModel::V2->height(Orientation::Portrait));
|
||||
}
|
||||
|
||||
public function test_v2_landscape_dimensions_are_swapped(): void
|
||||
{
|
||||
$this->assertSame(1600, DeviceModel::V2->width(Orientation::Landscape));
|
||||
$this->assertSame(1200, DeviceModel::V2->height(Orientation::Landscape));
|
||||
}
|
||||
|
||||
public function test_v2_native_dimensions_ignore_orientation(): void
|
||||
{
|
||||
$this->assertSame(1200, DeviceModel::V2->nativeWidth());
|
||||
$this->assertSame(1600, DeviceModel::V2->nativeHeight());
|
||||
}
|
||||
|
||||
public function test_v2_native_orientation_is_portrait(): void
|
||||
{
|
||||
$this->assertSame(Orientation::Portrait, DeviceModel::V2->nativeOrientation());
|
||||
}
|
||||
|
||||
public function test_panel_id_round_trips(): void
|
||||
{
|
||||
$this->assertSame(DeviceModel::V1, DeviceModel::fromPanelId(DeviceModel::V1->panelId()));
|
||||
$this->assertSame(DeviceModel::V2, DeviceModel::fromPanelId(DeviceModel::V2->panelId()));
|
||||
}
|
||||
|
||||
public function test_panel_ids_are_distinct(): void
|
||||
{
|
||||
$this->assertNotSame(DeviceModel::V1->panelId(), DeviceModel::V2->panelId());
|
||||
}
|
||||
|
||||
public function test_from_panel_id_returns_null_for_unknown(): void
|
||||
{
|
||||
$this->assertNull(DeviceModel::fromPanelId('not-a-real-panel'));
|
||||
$this->assertNull(DeviceModel::fromPanelId(''));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user