5.2. PikaStdDevice standard device

PikaStdDevice is an abstract device model that provides a unified peripheral API across platforms.

5.2.1. Install

  • Add PikaStdDevice dependency in requestment.txt.
  1. PikaStdDevice==v1.4.3
  • Run pikaPackage.exe

5.2.2. Why have standard equipment modules

What is a standard equipment module? Let’s start with other scripting technologies, such as MicroPython, there is no unified peripheral calling API, which makes users need to re-learn the API when using different platforms. For example, the following is the code for MicroPython to drive GPIO on the STM32F4 platform .

_images/1638495380966-02a52d33-9986-401c-a7e1-136ce71ad53e.webp

This is for ESP8266

_images/1638495381179-e6afcca5-7f32-4a2f-a531-10f6b106db15.webp

It can be clearly seen that when selecting the pin of the pin, one uses a string, while the other uses an integer number. When controlling the level, one uses the high(), low() methods, while the other uses the high() and low() methods. An API standard driven by on(), off() methods, in short, is confusing. Is there any way to unify the APIs of peripherals, so that users only need to be familiar with a set of APIs and can be used on any platform? There is a method, that is, the PikaStdDevice standard device driver module.

5.2.3. module structure

https://user-images.githubusercontent.com/88232613/171090021-2c5667b2-4656-4e44-9ade-f869e047007e.png

PikaStdDevice is an abstract device driver module that defines all user APIs. As long as the driver modules of each platform inherit from PikaStdDevice, they can obtain the same user API, and PikaStdDevice will indirectly call the platform driver and rewrite the underlying layer through polymorphism. The platform driver can work on different platforms.

5.2.4. Module example

Taking the GPIO module as an example, the following is the user API defined by PikaStdDevice

  1. class GPIO(TinyObj):
  2. def __init__(self):
  3. pass
  4. def init(self):
  5. pass
  6. def setPin(self, pinName: str):
  7. pass
  8. def setId(self, id: int):
  9. pass
  10. def getId(self) -> int:
  11. pass
  12. def getPin(self) -> str:
  13. pass
  14. def setMode(self, mode: str):
  15. pass
  16. def getMode(self) -> str:
  17. pass
  18. def setPull(self, pull: str):
  19. pass
  20. def enable(self):
  21. pass
  22. def disable(self):
  23. pass
  24. def high(self):
  25. pass
  26. def low(self):
  27. pass
  28. def read(self) -> int:
  29. pass

The following are the platform drivers that PikaStdDevice needs to rewrite

  1. # need be overrid
  2. def platformHigh(self):
  3. pass
  4. # need override
  5. def platformLow(self):
  6. pass
  7. # need override
  8. def platformEnable(self):
  9. pass
  10. # need override
  11. def platformDisable(self):
  12. pass
  13. # need override
  14. def platformSetMode(self):
  15. pass
  16. # need override
  17. def platformRead(self):
  18. pass

And the GPIO module of CH32V103 we want to make is inherited from the standard driver module.

  1. class GPIO(PikaStdDevice.GPIO):
  2. # override
  3. def platformHigh(self):
  4. pass
  5. # override
  6. def platformLow(self):
  7. pass
  8. # override
  9. def platformEnable(self):
  10. pass
  11. # override
  12. def platformDisable(self):
  13. pass
  14. # override
  15. def platformSetMode(self):
  16. pass
  17. # override
  18. def platformRead(self):
  19. pass

Through this method, we can make the STM32 driver module, CH32 driver module, and ESP32 driver module have the same user API. As long as users are familiar with a set of APIs, they can easily use all platforms that support the PikaScript standard driver module. The following are some of the C native driver functions that are registered in the driver module

  1. void CH32V103_GPIO_platformEnable(PikaObj *self){
  2. char *pin = obj_getStr(self, "pin");
  3. char *mode = obj_getStr(self, "mode");
  4. GPIO_TypeDef *GPIO_group = get_GPIO_group(pin);
  5. uint16_t GPIO_pin = get_GPIO_pin(pin);
  6. GPIOMode_TypeDef GPIO_mode = get_GPIO_mode(mode);
  7. uint32_t GPIO_clock_group = get_GPIO_Clock_group(pin);
  8. GPIO_InitTypeDef GPIO_InitStructure;
  9. RCC_APB2PeriphClockCmd(GPIO_clock_group,ENABLE);
  10. GPIO_InitStructure.GPIO_Pin = GPIO_pin;
  11. GPIO_InitStructure.GPIO_Mode = GPIO_mode;
  12. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  13. GPIO_Init(GPIO_group, &GPIO_InitStructure);
  14. }
  15. void CH32V103_GPIO_platformHigh(PikaObj *self){
  16. char *pin = obj_getStr(self, "pin");
  17. GPIO_TypeDef *GPIO_group = get_GPIO_group(pin);
  18. uint16_t GPIO_pin = get_GPIO_pin(pin);
  19. GPIO_WriteBit(GPIO_group, GPIO_pin, Bit_SET);
  20. }