| /* |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * Copyright (c) 2019 Google LLC. |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <LcdPainter.h> |
| |
| using namespace chip::app::Clusters::WindowCovering; |
| |
| constexpr uint32_t sTiltIcon[] = { |
| 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xc1ffffc3, 0xc1ffffc3, |
| 0xc1ffffc3, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, |
| 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, |
| 0xc003c003, 0xc003c003, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff, |
| }; |
| |
| constexpr uint32_t sLiftIcon[] = { |
| 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0f00003, 0xc0f00003, |
| 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, |
| 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0ffffc3, |
| 0xc0ffffc3, 0xc0ffffc3, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff, |
| }; |
| |
| constexpr uint32_t sOneIcon[] = { |
| 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc00fe003, 0xc01fe003, 0xc03fe003, |
| 0xc07fe003, 0xc0fbe003, 0xc1f3e003, 0xc3e3e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, |
| 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc3ffffc3, |
| 0xc3ffffc3, 0xc3ffffc3, 0xc3ffffc3, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff, |
| }; |
| |
| constexpr uint32_t sTwoIcon[] = { |
| 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc07ffe03, 0xc0ffff03, 0xc1ffff83, |
| 0xc3ffffc3, 0xc3f00fc3, 0xc3e007c3, 0xc3e007c3, 0xc00007c3, 0xc00007c3, 0xc0000fc3, 0xc00fff83, |
| 0xc03fff03, 0xc07ffe03, 0xc0fc0003, 0xc1f80003, 0xc1f00003, 0xc3e00003, 0xc3e00003, 0xc3ffffc3, |
| 0xc3ffffc3, 0xc3ffffc3, 0xc3ffffc3, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff, |
| }; |
| |
| PixelPainter::PixelPainter(uint16_t lift, uint16_t tilt) : mLift(lift), mTilt(tilt) {} |
| |
| CompositePainter::CompositePainter(uint16_t lift, uint16_t tilt, PixelPainter * painter1, PixelPainter * painter2, |
| PixelPainter * painter3) : |
| PixelPainter(lift, tilt), |
| mPainter1(painter1), mPainter2(painter2), mPainter3(painter3) |
| {} |
| |
| uint8_t CompositePainter::Color(uint32_t x, uint32_t y) |
| { |
| int8_t pixel = -1; |
| if (mPainter1) |
| { |
| pixel = mPainter1->Color(x, y); |
| if (pixel >= 0) |
| { |
| return pixel; |
| } |
| } |
| if (mPainter2) |
| { |
| pixel = mPainter2->Color(x, y); |
| if (pixel >= 0) |
| { |
| return pixel; |
| } |
| } |
| if (mPainter3) |
| { |
| pixel = mPainter3->Color(x, y); |
| if (pixel >= 0) |
| { |
| return pixel; |
| } |
| } |
| return pixel; |
| } |
| |
| uint8_t FramePainter::Color(uint32_t x, uint32_t y) |
| { |
| if (x < LCD_FRAME_SIZE || x >= (LCD_SIZE - LCD_FRAME_SIZE) || y < LCD_FRAME_SIZE || y >= (LCD_SIZE - LCD_FRAME_SIZE)) |
| { |
| if (x < LCD_MARGIN_SIZE || x >= (LCD_SIZE - LCD_MARGIN_SIZE) || y < LCD_MARGIN_SIZE || y >= (LCD_SIZE - LCD_MARGIN_SIZE)) |
| { |
| return 0; |
| } |
| else |
| { |
| return (x < (LCD_MARGIN_SIZE + LCD_BORDER_SIZE)) || (x >= (LCD_SIZE - LCD_BORDER_SIZE - LCD_MARGIN_SIZE)) || |
| (y < (LCD_MARGIN_SIZE + LCD_BORDER_SIZE)) || (y >= (LCD_SIZE - LCD_BORDER_SIZE - LCD_MARGIN_SIZE)); |
| } |
| } |
| return -1; |
| } |
| |
| IconPainter::IconPainter(uint16_t lift, uint16_t tilt, LcdIcon icon) : PixelPainter(lift, tilt), mIcon(icon) |
| { |
| mIconSize = sizeof(sTiltIcon) / sizeof(uint32_t); |
| mIconOffset = (LCD_SIZE - mIconSize) / 2; |
| } |
| |
| uint8_t IconPainter::Color(uint32_t x, uint32_t y) |
| { |
| const uint32_t * icon = nullptr; |
| switch (mIcon) |
| { |
| case LcdIcon::One: |
| icon = sOneIcon; |
| break; |
| case LcdIcon::Two: |
| icon = sTwoIcon; |
| break; |
| case LcdIcon::Lift: |
| icon = sLiftIcon; |
| break; |
| case LcdIcon::Tilt: |
| icon = sTiltIcon; |
| break; |
| default: |
| return -1; |
| } |
| if (x >= mIconOffset && x < (mIconOffset + mIconSize) && y >= mIconOffset && y < (mIconOffset + mIconSize)) |
| { |
| uint32_t x0 = x - mIconOffset; |
| uint32_t y0 = y - mIconOffset; |
| return (icon[y0] & (1 << (31 - x0))) > 0; |
| } |
| return -1; |
| } |
| |
| uint8_t VerticalShadePainter::Color(uint32_t x, uint32_t y) |
| { |
| return (y % 2) && y < (uint32_t) (LCD_FRAME_SIZE + mLift); |
| } |
| |
| uint8_t HorizontalShadePainter::Color(uint32_t x, uint32_t y) |
| { |
| return (x % 2) && x < (uint32_t) (LCD_FRAME_SIZE + mLift); |
| } |
| |
| VerticalBlindPainter::VerticalBlindPainter(uint16_t lift, uint16_t tilt) : PixelPainter(lift, tilt) |
| { |
| mBandSize = (LCD_COVER_SIZE / sBandCount); |
| } |
| |
| uint8_t VerticalBlindPainter::Color(uint32_t x, uint32_t y) |
| { |
| if (x % 2) |
| { |
| return 0; |
| } |
| else |
| { |
| uint32_t closedCount = (mLift + 1) / mBandSize; |
| uint32_t bandCount = (y - LCD_FRAME_SIZE) / mBandSize; |
| // ChipLogProgress(Zcl, "BLIND: ccount:%u, ccount:%u", clusterId); |
| if (bandCount <= closedCount) |
| { |
| return y <= (LCD_FRAME_SIZE + mBandSize * bandCount + mTilt); |
| } |
| else |
| { |
| return 0; |
| } |
| } |
| } |
| |
| PixelPainter * LcdPainter::GetCoverPainter(Type type, uint16_t lift, uint16_t tilt) |
| { |
| switch (type) |
| { |
| case Type::kRollerShade: |
| case Type::kRollerShade2Motor: |
| case Type::kRollerShadeExterior: |
| case Type::kRollerShadeExterior2Motor: |
| return new VerticalShadePainter(lift, tilt); |
| case Type::kDrapery: |
| case Type::kAwning: |
| return new HorizontalShadePainter(lift, tilt); |
| case Type::kShutter: |
| case Type::kTiltBlindTiltOnly: |
| case Type::kTiltBlindLiftAndTilt: |
| return new VerticalBlindPainter(lift, tilt); |
| case Type::kProjectorScreen: |
| case Type::kUnknown: |
| default: |
| return new VerticalShadePainter(lift, tilt); |
| } |
| |
| return nullptr; |
| } |
| |
| void LcdPainter::Paint(SilabsLCD & lcd, Type type, uint16_t lift, uint16_t tilt, LcdIcon icon) |
| { |
| FramePainter framePaint = FramePainter(lift, tilt); |
| IconPainter iconPaint = IconPainter(lift, tilt, icon); |
| PixelPainter * coverPaint = GetCoverPainter(type, lift, tilt); |
| CompositePainter compositePaint = CompositePainter(lift, tilt, &framePaint, &iconPaint, coverPaint); |
| void * context = lcd.Context(); |
| |
| lcd.Clear(); |
| |
| for (int i = 0; i < LCD_SIZE; i++) |
| { |
| for (int j = 0; j < LCD_SIZE; j++) |
| { |
| if (compositePaint.Color(i, j)) |
| { |
| lcd.DrawPixel(context, i, j); |
| } |
| } |
| } |
| lcd.Update(); |
| delete coverPaint; |
| } |