Initial commit
10
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
firmware/pico-sdk
|
||||
firmware/source/build/
|
||||
firmware/source/config.h.in
|
||||
*.idea
|
||||
dist
|
||||
u2if.egg-info
|
||||
build
|
||||
*.txt.user
|
||||
__pycache__
|
||||
venv/
|
||||
5
LICENSE
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
See License files for the three parts of the u2if project:
|
||||
- python library: source/LICENSE
|
||||
- firmware for raspberry pico: firmware/source/LICENSE
|
||||
- KiCad dev. board: board/LICENSE
|
||||
|
||||
114
README.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# u2if project
|
||||
|
||||
u2if(USB to interfaces) is an attempt to implement some of the MicroPython "machine" module functionalities on a computer.
|
||||
The goal is to be able to communicate with breakout boards (sensors, lcd...) simply from a python program on x86 machine. It uses a Raspberry PICO microcontroller to make the interface between the computer (USB) and peripherals/protocols.
|
||||
|
||||
<p align="center"><img src="images/principle.png"/></p>
|
||||
|
||||
**Python led swith on/off**:
|
||||
```python
|
||||
import time
|
||||
from machine import u2if, Pin
|
||||
|
||||
# Initialize GPIO to output and set the value HIGH
|
||||
led = Pin(u2if.GP_3, Pin.OUT, value=Pin.HIGH)
|
||||
time.sleep(1)
|
||||
# Switch off the led
|
||||
led.value(Pin.LOW)
|
||||
```
|
||||
|
||||
## Caution
|
||||
|
||||
It is in experimental state and not everything has been tested. Use with caution. It is supposed to work on windows, linux and Mac.
|
||||
To work in Linux in non-root, an udev rules has to be added (See [Firmware readme](firmware/README.md)).
|
||||
|
||||
|
||||
## Why this project ?
|
||||
When I want to retrieve values from a sensor or even to play with a led or a button from the PC, I make an arduino program that communicate to the PC via the serial port. That umplies to define a serial "protocol" between the PC and the arduino and it is not necessarily reusable because it is specific.
|
||||
|
||||
Solutions already exist, for example [Blinka](https://github.com/adafruit/Adafruit_Blinka) from Adafruit via the FT2232H in CircuitPython or pyftdi in Python with the same IC.
|
||||
|
||||
Nevertheless I find it interesting to implement a majority of the functionalities of the machine module and add other protocols.
|
||||
|
||||
## Implemented Interfaces
|
||||
The following features are coded:
|
||||
|
||||
* machine.Pin: input (+irq, +debounced), output (+pull down/up).
|
||||
* machine.Signal
|
||||
* machine.ADC: read (12bits)
|
||||
* machine.UART
|
||||
* machine.I2C
|
||||
* machine.SPI
|
||||
* machine.PWM
|
||||
|
||||
Other features to do:
|
||||
* WS2812B led driver
|
||||
* I2S
|
||||
* ...
|
||||
|
||||
## Licenses and Project directories
|
||||
This repository is presented as the sources of a python project ([License](source/LICENSE)).
|
||||
But it also contains the following projects:
|
||||
|
||||
* [firmware](firmware/): PICO firmware, binary and C++ source [License](firmware/source/LICENSE).
|
||||
* [examples](examples/): Python program examples.
|
||||
* [board](board/): Example of a pico headers board for this project ([License](firmware/source/LICENSE)).
|
||||
|
||||
|
||||
## How to use it
|
||||
|
||||
### Upload PICO firmware
|
||||
See [Firmware README](firmware/README.md)
|
||||
|
||||
### Install u2if python package
|
||||
|
||||
Install python package from release file (u2if-*.*.tar.gz) with python3 -m pip install dist/u2if-*.*.tar.gz
|
||||
|
||||
## Build u2if python package
|
||||
|
||||
To build package if wanted :
|
||||
|
||||
* If needed, install build: python3 -m pip install --upgrade build
|
||||
* Build it: python3 -m build
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
There is no documentation but [examples](examples/) can help to use this library :
|
||||
|
||||
* Led On/Off
|
||||
* Switch with or whithour irq and debouncing
|
||||
* PWM controlling servo-motor
|
||||
* Display testing: SSD1306 (I2C and SPI), GC9A01 (round lcd)
|
||||
* Some sensors simple test: MPU9250 (IMU), VL53L0X (range), BMP280(Temp)
|
||||
* UART read/Write
|
||||
* Analog read.
|
||||
* Rotrary encoder
|
||||
* I2C scan
|
||||
* ...
|
||||
|
||||
|
||||
## u2if pinout
|
||||
|
||||
For simplicity, the pins of the SPI, I2C and UART devices have been fixed. If a peripheral is not used, its pins can be used as a classic I/O.
|
||||
<p align="center"><img src="images/u2if_pinout.png"/></p>
|
||||
|
||||
## Troubleshooting
|
||||
### Import error using MicroPython module
|
||||
#### import ustruct
|
||||
|
||||
The ustruct module is belongs by micropython. There is a micropython-cpython-ustruct compatibility module, but it doesn't seem to work for me. If necessary modify:
|
||||
```python
|
||||
import ustruct
|
||||
```
|
||||
to:
|
||||
```python
|
||||
import struct as ustruct
|
||||
```
|
||||
|
||||
#### import utime & const
|
||||
|
||||
Install micropython-cpython-utime and micropython-cpython-micropython.
|
||||
|
||||
|
||||
|
||||
30
board/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# From https://raw.githubusercontent.com/github/gitignore/master/KiCad.gitignore
|
||||
# For PCBs designed using KiCad: http://www.kicad-pcb.org/
|
||||
# Format documentation: http://kicad-pcb.org/help/file-formats/
|
||||
|
||||
# Temporary files
|
||||
*.000
|
||||
*.bak
|
||||
*.bck
|
||||
*.kicad_pcb-bak
|
||||
*.kicad_sch-bak
|
||||
*.kicad_prl
|
||||
*.sch-bak
|
||||
*~
|
||||
_autosave-*
|
||||
*.tmp
|
||||
*-save.pro
|
||||
*-save.kicad_pcb
|
||||
fp-info-cache
|
||||
|
||||
# Netlist files (exported from Eeschema)
|
||||
*.net
|
||||
|
||||
# Autorouter files (exported from Pcbnew)
|
||||
*.dsn
|
||||
*.ses
|
||||
|
||||
# Exported BOM files
|
||||
*.xml
|
||||
*.csv
|
||||
|
||||
89
board/LICENSE
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
Project u2if (KiCad dev. board):
|
||||
--------------------------------
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 execuc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
|
||||
External library licenses:
|
||||
--------------------------
|
||||
|
||||
--------------
|
||||
KiCad library:
|
||||
--------------
|
||||
|
||||
Creative Commons CC-BY-SA 4.0 License
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Raspberry Pico KiCad library (https://github.com/HeadBoffin/RP_Silicon_KiCad):
|
||||
------------------------------------------------------------------------------
|
||||
The original Raspberry Pi Foundation / Trading license:
|
||||
|
||||
These design files are made available openly, with no limitations.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this design for
|
||||
any purpose with or without fee is hereby granted.
|
||||
|
||||
THE DESIGN IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS DESIGN INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
|
||||
FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS DESIGN.
|
||||
|
||||
|
||||
Which looks rather like the UnLicense:
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
12
board/README.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# PICO headers dev board
|
||||
|
||||
<p align="center"><img src="images/pcb_3d.png"/></p>
|
||||
|
||||
It's a kicad project of a PCB with some I/O but mostly headers.
|
||||
Zipped gerber file is available: [Gerber file](pico-dev/gerber/pico-dev.zip)
|
||||
|
||||
**Caution**: I am not an electronic engineer, check schematics and PCB before using it !
|
||||
|
||||
<p align="center"><img src="images/pcb.jpg"/></p>
|
||||
|
||||
|
||||
BIN
board/images/pcb.jpg
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
board/images/pcb_3d.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
board/pico-dev/doc/0-96_oled_i2c_ssd1306.jpg
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
board/pico-dev/doc/GY91-IMU-Pin.jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
board/pico-dev/doc/raspberry_pi_pico_pinout.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
|
|
@ -0,0 +1,37 @@
|
|||
(module Crystal_SMD_HC49-US (layer F.Cu) (tedit 5F0C7995)
|
||||
(descr "SMD Crystal HC-49-SD http://cdn-reichelt.de/documents/datenblatt/B400/xxx-HC49-SMD.pdf, 11.4x4.7mm^2 package")
|
||||
(tags "SMD SMT crystal")
|
||||
(attr smd)
|
||||
(fp_text reference Y1 (at 0 -3.55) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value ABLS-12.000MHZ-B4-T (at 0 3.55) (layer F.Fab)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start -6.7 1.3) (end -6.7 2.55) (layer F.SilkS) (width 0.12))
|
||||
(fp_text user %R (at 0 0) (layer F.Fab)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start -5.7 -2.35) (end -5.7 2.35) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start -5.7 2.35) (end 5.7 2.35) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start 5.7 2.35) (end 5.7 -2.35) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start 5.7 -2.35) (end -5.7 -2.35) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start -3.015 -2.115) (end 3.015 -2.115) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start -3.015 2.115) (end 3.015 2.115) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start 5.9 -2.55) (end -6.7 -2.55) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -6.7 -2.55) (end -6.7 -1.3) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -6.7 2.55) (end 5.9 2.55) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -6.8 -2.6) (end -6.8 2.6) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -6.8 2.6) (end 6.8 2.6) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 6.8 2.6) (end 6.8 -2.6) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 6.8 -2.6) (end -6.8 -2.6) (layer F.CrtYd) (width 0.05))
|
||||
(fp_arc (start -3.015 0) (end -3.015 -2.115) (angle -180) (layer F.Fab) (width 0.1))
|
||||
(fp_arc (start 3.015 0) (end 3.015 -2.115) (angle 180) (layer F.Fab) (width 0.1))
|
||||
(pad 1 smd rect (at -4.5 0) (size 5.6 2.1) (layers F.Cu F.Paste F.Mask))
|
||||
(pad 2 smd rect (at 4.5 0) (size 5.6 2.1) (layers F.Cu F.Paste F.Mask))
|
||||
(model ${KISYS3DMOD}/Crystal.3dshapes/Crystal_SMD_HC49-SD.wrl
|
||||
(at (xyz 0 0 0))
|
||||
(scale (xyz 1 1 1))
|
||||
(rotate (xyz 0 0 0))
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
(module RP2040-QFN-56 (layer F.Cu) (tedit 5EF32B43)
|
||||
(descr "QFN, 56 Pin (http://www.cypress.com/file/416486/download#page=40), generated with kicad-footprint-generator ipc_dfn_qfn_generator.py")
|
||||
(tags "QFN DFN_QFN")
|
||||
(attr smd)
|
||||
(fp_text reference REF** (at 0 -4.82) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value Pico2040-QFN-56 (at 0 4.82) (layer F.Fab)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user %R (at 0 0) (layer F.Fab)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start 4.12 -4.12) (end -4.12 -4.12) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 4.12 4.12) (end 4.12 -4.12) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -4.12 4.12) (end 4.12 4.12) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -4.12 -4.12) (end -4.12 4.12) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -3.5 -2.5) (end -2.5 -3.5) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start -3.5 3.5) (end -3.5 -2.5) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start 3.5 3.5) (end -3.5 3.5) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start 3.5 -3.5) (end 3.5 3.5) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start -2.5 -3.5) (end 3.5 -3.5) (layer F.Fab) (width 0.1))
|
||||
(fp_line (start -2.96 -3.61) (end -3.61 -3.61) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 3.61 3.61) (end 3.61 2.96) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 2.96 3.61) (end 3.61 3.61) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -3.61 3.61) (end -3.61 2.96) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -2.96 3.61) (end -3.61 3.61) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 3.61 -3.61) (end 3.61 -2.96) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 2.96 -3.61) (end 3.61 -3.61) (layer F.SilkS) (width 0.12))
|
||||
(pad 56 smd roundrect (at -2.6 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 55 smd roundrect (at -2.2 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 54 smd roundrect (at -1.8 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 53 smd roundrect (at -1.4 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 52 smd roundrect (at -1 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 51 smd roundrect (at -0.6 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 50 smd roundrect (at -0.2 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 49 smd roundrect (at 0.2 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 48 smd roundrect (at 0.6 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 47 smd roundrect (at 1 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 46 smd roundrect (at 1.4 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 45 smd roundrect (at 1.8 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 44 smd roundrect (at 2.2 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 43 smd roundrect (at 2.6 -3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 42 smd roundrect (at 3.4375 -2.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 41 smd roundrect (at 3.4375 -2.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 40 smd roundrect (at 3.4375 -1.8) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 39 smd roundrect (at 3.4375 -1.4) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 38 smd roundrect (at 3.4375 -1) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 37 smd roundrect (at 3.4375 -0.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 36 smd roundrect (at 3.4375 -0.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 35 smd roundrect (at 3.4375 0.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 34 smd roundrect (at 3.4375 0.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 33 smd roundrect (at 3.4375 1) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 32 smd roundrect (at 3.4375 1.4) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 31 smd roundrect (at 3.4375 1.8) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 30 smd roundrect (at 3.4375 2.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 29 smd roundrect (at 3.4375 2.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 28 smd roundrect (at 2.6 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 27 smd roundrect (at 2.2 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 26 smd roundrect (at 1.8 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 25 smd roundrect (at 1.4 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 24 smd roundrect (at 1 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 23 smd roundrect (at 0.6 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 22 smd roundrect (at 0.2 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 21 smd roundrect (at -0.2 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 20 smd roundrect (at -0.6 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 19 smd roundrect (at -1 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 18 smd roundrect (at -1.4 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 17 smd roundrect (at -1.8 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 16 smd roundrect (at -2.2 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 15 smd roundrect (at -2.6 3.4375) (size 0.2 0.875) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 14 smd roundrect (at -3.4375 2.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 13 smd roundrect (at -3.4375 2.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 12 smd roundrect (at -3.4375 1.8) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 11 smd roundrect (at -3.4375 1.4) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 10 smd roundrect (at -3.4375 1) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 9 smd roundrect (at -3.4375 0.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 8 smd roundrect (at -3.4375 0.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 7 smd roundrect (at -3.4375 -0.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 6 smd roundrect (at -3.4375 -0.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 5 smd roundrect (at -3.4375 -1) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 4 smd roundrect (at -3.4375 -1.4) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 3 smd roundrect (at -3.4375 -1.8) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 2 smd roundrect (at -3.4375 -2.2) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad 1 smd roundrect (at -3.4375 -2.6) (size 0.875 0.2) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
|
||||
(pad "" smd roundrect (at 0.6375 0.6375) (size 1.084435 1.084435) (layers F.Paste) (roundrect_rratio 0.230535))
|
||||
(pad "" smd roundrect (at 0.6375 -0.6375) (size 1.084435 1.084435) (layers F.Paste) (roundrect_rratio 0.230535))
|
||||
(pad "" smd roundrect (at -0.6375 0.6375) (size 1.084435 1.084435) (layers F.Paste) (roundrect_rratio 0.230535))
|
||||
(pad "" smd roundrect (at -0.6375 -0.6375) (size 1.084435 1.084435) (layers F.Paste) (roundrect_rratio 0.230535))
|
||||
(pad 57 thru_hole circle (at 1.275 1.275) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at 0 1.275) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at -1.275 1.275) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at 1.275 0) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at -1.275 0) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at 1.275 -1.275) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at 0 -1.275) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 thru_hole circle (at -1.275 -1.275) (size 0.6 0.6) (drill 0.35) (layers *.Cu))
|
||||
(pad 57 smd roundrect (at 0 0) (size 3.2 3.2) (layers F.Cu F.Mask) (roundrect_rratio 0.045))
|
||||
(model ${KISYS3DMOD}/Package_DFN_QFN.3dshapes/QFN-56-1EP_7x7mm_P0.4mm_EP5.6x5.6mm.wrl
|
||||
(at (xyz 0 0 0))
|
||||
(scale (xyz 1 1 1))
|
||||
(rotate (xyz 0 0 0))
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
(module RPi_Pico_SMD_TH (layer F.Cu) (tedit 5F638C80)
|
||||
(descr "Through hole straight pin header, 2x20, 2.54mm pitch, double rows")
|
||||
(tags "Through hole pin header THT 2x20 2.54mm double row")
|
||||
(fp_text reference REF** (at 0 0) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value RPi_Pico_SMD_TH (at 0 2.159) (layer F.Fab)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start 1.1 25.5) (end 1.5 25.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -1.5 25.5) (end -1.1 25.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 25.5) (end 3.7 25.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 15.1) (end 10.5 15.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 7.4) (end 10.5 7.8) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -18) (end 10.5 -17.6) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -25.5) (end 10.5 -25.2) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -2.7) (end 10.5 -2.3) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 12.5) (end 10.5 12.9) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -7.8) (end 10.5 -7.4) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -12.9) (end 10.5 -12.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -0.2) (end 10.5 0.2) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 4.9) (end 10.5 5.3) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 20.1) (end 10.5 20.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 22.7) (end 10.5 23.1) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 17.6) (end 10.5 18) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -15.4) (end 10.5 -15) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -23.1) (end 10.5 -22.7) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -20.5) (end 10.5 -20.1) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 10) (end 10.5 10.4) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 2.3) (end 10.5 2.7) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -5.3) (end 10.5 -4.9) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start 10.5 -10.4) (end 10.5 -10) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 22.7) (end -10.5 23.1) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 20.1) (end -10.5 20.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 17.6) (end -10.5 18) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 15.1) (end -10.5 15.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 12.5) (end -10.5 12.9) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 10) (end -10.5 10.4) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 7.4) (end -10.5 7.8) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 4.9) (end -10.5 5.3) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 2.3) (end -10.5 2.7) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -0.2) (end -10.5 0.2) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -2.7) (end -10.5 -2.3) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -5.3) (end -10.5 -4.9) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -7.8) (end -10.5 -7.4) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -10.4) (end -10.5 -10) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -12.9) (end -10.5 -12.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -15.4) (end -10.5 -15) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -18) (end -10.5 -17.6) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -20.5) (end -10.5 -20.1) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -23.1) (end -10.5 -22.7) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -25.5) (end -10.5 -25.2) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -7.493 -22.833) (end -7.493 -25.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -22.833) (end -7.493 -22.833) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -3.7 25.5) (end -10.5 25.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -10.5 -25.5) (end 10.5 -25.5) (layer F.SilkS) (width 0.12))
|
||||
(fp_line (start -11 26) (end -11 -26) (layer F.CrtYd) (width 0.12))
|
||||
(fp_line (start 11 26) (end -11 26) (layer F.CrtYd) (width 0.12))
|
||||
(fp_line (start 11 -26) (end 11 26) (layer F.CrtYd) (width 0.12))
|
||||
(fp_line (start -11 -26) (end 11 -26) (layer F.CrtYd) (width 0.12))
|
||||
(fp_line (start -10.5 -24.2) (end -9.2 -25.5) (layer F.Fab) (width 0.12))
|
||||
(fp_line (start -10.5 25.5) (end -10.5 -25.5) (layer F.Fab) (width 0.12))
|
||||
(fp_line (start 10.5 25.5) (end -10.5 25.5) (layer F.Fab) (width 0.12))
|
||||
(fp_line (start 10.5 -25.5) (end 10.5 25.5) (layer F.Fab) (width 0.12))
|
||||
(fp_line (start -10.5 -25.5) (end 10.5 -25.5) (layer F.Fab) (width 0.12))
|
||||
(fp_text user %R (at 0 0 180) (layer F.Fab)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP1 (at -12.9 -21.6 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP2 (at -12.9 -16.51 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP0 (at -12.8 -24.13 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP3 (at -12.8 -13.97 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP4 (at -12.8 -11.43 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP5 (at -12.8 -8.89 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP6 (at -12.8 -3.81 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP7 (at -12.7 -1.3 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP8 (at -12.8 1.27 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP9 (at -12.8 3.81 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP10 (at -13.054 8.89 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP11 (at -13.2 11.43 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP12 (at -13.2 13.97 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP13 (at -13.054 16.51 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP14 (at -13.1 21.59 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP15 (at -13.054 24.13 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP16 (at 13.054 24.13 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP17 (at 13.054 21.59 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP18 (at 13.054 16.51 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP19 (at 13.054 13.97 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP20 (at 13.054 11.43 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP21 (at 13.054 8.9 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP22 (at 13.054 3.81 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user RUN (at 13 1.27 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP26 (at 13.054 -1.27 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP27 (at 13.054 -3.8 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GP28 (at 13.054 -9.144 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user ADC_VREF (at 14 -12.5 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user 3V3 (at 12.9 -13.9 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user 3V3_EN (at 13.7 -17.2 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user VSYS (at 13.2 -21.59 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user VBUS (at 13.3 -24.2 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at -12.8 -19.05 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at -12.8 -6.35 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at -12.8 6.35 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at -12.8 19.05 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at 12.8 19.05 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at 12.8 6.35 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user GND (at 12.8 -19.05 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user AGND (at 13.054 -6.35 45) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user SWCLK (at -5.7 26.2) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_text user SWDIO (at 5.6 26.2) (layer F.SilkS)
|
||||
(effects (font (size 0.8 0.8) (thickness 0.15)))
|
||||
)
|
||||
(fp_poly (pts (xy -1.5 -16.5) (xy -3.5 -16.5) (xy -3.5 -18.5) (xy -1.5 -18.5)) (layer Dwgs.User) (width 0.1))
|
||||
(fp_poly (pts (xy -1.5 -14) (xy -3.5 -14) (xy -3.5 -16) (xy -1.5 -16)) (layer Dwgs.User) (width 0.1))
|
||||
(fp_poly (pts (xy -1.5 -11.5) (xy -3.5 -11.5) (xy -3.5 -13.5) (xy -1.5 -13.5)) (layer Dwgs.User) (width 0.1))
|
||||
(fp_poly (pts (xy 3.7 -20.2) (xy -3.7 -20.2) (xy -3.7 -24.9) (xy 3.7 -24.9)) (layer Dwgs.User) (width 0.1))
|
||||
(fp_text user "Copper Keepouts shown on Dwgs layer" (at 0.1 -30.2) (layer Cmts.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(pad 1 thru_hole oval (at -8.89 -24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 2 thru_hole oval (at -8.89 -21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 3 thru_hole rect (at -8.89 -19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 4 thru_hole oval (at -8.89 -16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 5 thru_hole oval (at -8.89 -13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 6 thru_hole oval (at -8.89 -11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 7 thru_hole oval (at -8.89 -8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 8 thru_hole rect (at -8.89 -6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 9 thru_hole oval (at -8.89 -3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 10 thru_hole oval (at -8.89 -1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 11 thru_hole oval (at -8.89 1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 12 thru_hole oval (at -8.89 3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 13 thru_hole rect (at -8.89 6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 14 thru_hole oval (at -8.89 8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 15 thru_hole oval (at -8.89 11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 16 thru_hole oval (at -8.89 13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 17 thru_hole oval (at -8.89 16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 18 thru_hole rect (at -8.89 19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 19 thru_hole oval (at -8.89 21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 20 thru_hole oval (at -8.89 24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 21 thru_hole oval (at 8.89 24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 22 thru_hole oval (at 8.89 21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 23 thru_hole rect (at 8.89 19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 24 thru_hole oval (at 8.89 16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 25 thru_hole oval (at 8.89 13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 26 thru_hole oval (at 8.89 11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 27 thru_hole oval (at 8.89 8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 28 thru_hole rect (at 8.89 6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 29 thru_hole oval (at 8.89 3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 30 thru_hole oval (at 8.89 1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 31 thru_hole oval (at 8.89 -1.27) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 32 thru_hole oval (at 8.89 -3.81) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 33 thru_hole rect (at 8.89 -6.35) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 34 thru_hole oval (at 8.89 -8.89) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 35 thru_hole oval (at 8.89 -11.43) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 36 thru_hole oval (at 8.89 -13.97) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 37 thru_hole oval (at 8.89 -16.51) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 38 thru_hole rect (at 8.89 -19.05) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 39 thru_hole oval (at 8.89 -21.59) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 40 thru_hole oval (at 8.89 -24.13) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 1 smd rect (at -8.89 -24.13) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 2 smd rect (at -8.89 -21.59) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 3 smd rect (at -8.89 -19.05) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 4 smd rect (at -8.89 -16.51) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 5 smd rect (at -8.89 -13.97) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 6 smd rect (at -8.89 -11.43) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 7 smd rect (at -8.89 -8.89) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 8 smd rect (at -8.89 -6.35) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 9 smd rect (at -8.89 -3.81) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 10 smd rect (at -8.89 -1.27) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 11 smd rect (at -8.89 1.27) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 12 smd rect (at -8.89 3.81) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 13 smd rect (at -8.89 6.35) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 14 smd rect (at -8.89 8.89) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 15 smd rect (at -8.89 11.43) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 16 smd rect (at -8.89 13.97) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 17 smd rect (at -8.89 16.51) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 18 smd rect (at -8.89 19.05) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 19 smd rect (at -8.89 21.59) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 20 smd rect (at -8.89 24.13) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 40 smd rect (at 8.89 -24.13) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 39 smd rect (at 8.89 -21.59) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 38 smd rect (at 8.89 -19.05) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 37 smd rect (at 8.89 -16.51) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 36 smd rect (at 8.89 -13.97) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 35 smd rect (at 8.89 -11.43) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 34 smd rect (at 8.89 -8.89) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 33 smd rect (at 8.89 -6.35) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 32 smd rect (at 8.89 -3.81) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 31 smd rect (at 8.89 -1.27) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 30 smd rect (at 8.89 1.27) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 29 smd rect (at 8.89 3.81) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 28 smd rect (at 8.89 6.35) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 27 smd rect (at 8.89 8.89) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 26 smd rect (at 8.89 11.43) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 25 smd rect (at 8.89 13.97) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 24 smd rect (at 8.89 16.51) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 23 smd rect (at 8.89 19.05) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 22 smd rect (at 8.89 21.59) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 21 smd rect (at 8.89 24.13) (size 3.5 1.7) (drill (offset 0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad "" np_thru_hole oval (at -2.725 -24) (size 1.8 1.8) (drill 1.8) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole oval (at 2.725 -24) (size 1.8 1.8) (drill 1.8) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole oval (at -2.425 -20.97) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole oval (at 2.425 -20.97) (size 1.5 1.5) (drill 1.5) (layers *.Cu *.Mask))
|
||||
(pad 41 smd rect (at -2.54 23.9 90) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 41 thru_hole oval (at -2.54 23.9) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 42 smd rect (at 0 23.9 90) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 42 thru_hole rect (at 0 23.9) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 43 smd rect (at 2.54 23.9 90) (size 3.5 1.7) (drill (offset -0.9 0)) (layers F.Cu F.Mask))
|
||||
(pad 43 thru_hole oval (at 2.54 23.9) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
)
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
(module ssd1306_I2c (layer F.Cu) (tedit 60538283)
|
||||
(fp_text reference REF** (at 0 10.033) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value ssd1306_I2c (at 0 0) (layer F.Fab)
|
||||
(effects (font (size 2 2) (thickness 0.3)))
|
||||
)
|
||||
(fp_line (start -13.65 -13.9) (end 13.65 -13.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 13.65 -13.9) (end 13.65 13.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -13.65 13.9) (end -7 13.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -13.65 -13.9) (end -13.65 13.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 7 13.9) (end 13.65 13.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -7 11.9) (end 7 11.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -7 13.9) (end -7 11.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 7 13.9) (end 7 11.9) (layer F.SilkS) (width 0.15))
|
||||
(fp_text user GND (at -3.81 -10.16) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.25)))
|
||||
)
|
||||
(fp_text user 3.3V (at -1.27 -8.382) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.25)))
|
||||
)
|
||||
(fp_line (start -1.27 -9.271) (end -1.27 -11.303) (layer F.SilkS) (width 0.15))
|
||||
(fp_text user SCL (at 1.27 -10.287) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.25)))
|
||||
)
|
||||
(fp_line (start 3.81 -9.271) (end 3.81 -11.303) (layer F.SilkS) (width 0.15))
|
||||
(fp_text user SDA (at 3.81 -8.382) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.25)))
|
||||
)
|
||||
(pad 1 thru_hole rect (at -3.81 -12.4) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 2 thru_hole circle (at -1.27 -12.4) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 3 thru_hole circle (at 1.27 -12.4) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad 4 thru_hole circle (at 3.81 -12.4) (size 1.7 1.7) (drill 1.02) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole circle (at -11.65 -11.9) (size 3 3) (drill 3) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole circle (at 11.65 -11.9) (size 3 3) (drill 3) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole circle (at -11.65 11.9) (size 3 3) (drill 3) (layers *.Cu *.Mask))
|
||||
(pad "" np_thru_hole circle (at 11.65 11.9) (size 3 3) (drill 3) (layers *.Cu *.Mask))
|
||||
)
|
||||
4
board/pico-dev/fp-lib-table
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(fp_lib_table
|
||||
(lib (name MCU_RaspberryPi_and_Boards)(type KiCad)(uri ${KIPRJMOD}/footprint/MCU_RaspberryPi_and_Boards.pretty)(options "")(descr ""))
|
||||
(lib (name oled_ssd1306)(type KiCad)(uri ${KIPRJMOD}/footprint/oled_ssd1306.pretty)(options "")(descr ""))
|
||||
)
|
||||
6365
board/pico-dev/gerber/pico-dev-B.Cu.gbr
Normal file
7081
board/pico-dev/gerber/pico-dev-B.Mask.gbr
Normal file
15
board/pico-dev/gerber/pico-dev-B.SilkS.gbr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1*
|
||||
G04 #@! TF.CreationDate,2021-03-18T17:53:01+01:00*
|
||||
G04 #@! TF.ProjectId,pico-dev,7069636f-2d64-4657-962e-6b696361645f,rev?*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Legend,Bot*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1) date jeu. 18 mars 2021 17:53:01 CET*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 APERTURE END LIST*
|
||||
M02*
|
||||
48
board/pico-dev/gerber/pico-dev-Edge.Cuts.gbr
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1*
|
||||
G04 #@! TF.CreationDate,2021-03-18T17:53:01+01:00*
|
||||
G04 #@! TF.ProjectId,pico-dev,7069636f-2d64-4657-962e-6b696361645f,rev?*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Profile,NP*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1) date jeu. 18 mars 2021 17:53:01 CET*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%ADD10C,0.150000*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
X112776000Y-25908000D02*
|
||||
X111760000Y-25400000D01*
|
||||
X122428000Y-25908000D02*
|
||||
X123444000Y-25400000D01*
|
||||
X112776000Y-25908000D02*
|
||||
X122428000Y-25908000D01*
|
||||
X123444000Y-25400000D02*
|
||||
X170180000Y-25400000D01*
|
||||
X73660000Y-27940000D02*
|
||||
X73660000Y-99060000D01*
|
||||
X172720000Y-27940000D02*
|
||||
X172720000Y-99060000D01*
|
||||
X76200000Y-101600000D02*
|
||||
G75*
|
||||
G02X73660000Y-99060000I0J2540000D01*
|
||||
G01*
|
||||
X172720000Y-99060000D02*
|
||||
G75*
|
||||
G02X170180000Y-101600000I-2540000J0D01*
|
||||
G01*
|
||||
X170180000Y-25400000D02*
|
||||
G75*
|
||||
G02X172720000Y-27940000I0J-2540000D01*
|
||||
G01*
|
||||
X73660000Y-27940000D02*
|
||||
G75*
|
||||
G02X76200000Y-25400000I2540000J0D01*
|
||||
G01*
|
||||
X76200000Y-25400000D02*
|
||||
X111760000Y-25400000D01*
|
||||
X170180000Y-101600000D02*
|
||||
X76200000Y-101600000D01*
|
||||
M02*
|
||||
6605
board/pico-dev/gerber/pico-dev-F.Cu.gbr
Normal file
5617
board/pico-dev/gerber/pico-dev-F.Mask.gbr
Normal file
7184
board/pico-dev/gerber/pico-dev-F.SilkS.gbr
Normal file
BIN
board/pico-dev/gerber/pico-dev-v0.1.0.zip
Normal file
BIN
board/pico-dev/gerber/pico-dev-v0.1.1.zip
Normal file
175
board/pico-dev/gerber/pico-dev.drl
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
M48
|
||||
;DRILL file {KiCad 5.0.2+dfsg1-1} date jeu. 18 mars 2021 17:53:03 CET
|
||||
;FORMAT={-:-/ absolute / inch / decimal}
|
||||
FMAT,2
|
||||
INCH,TZ
|
||||
T1C0.0315
|
||||
T2C0.0354
|
||||
T3C0.0394
|
||||
T4C0.0402
|
||||
T5C0.0433
|
||||
T6C0.0591
|
||||
T7C0.0709
|
||||
T8C0.1181
|
||||
T9C0.1260
|
||||
%
|
||||
G90
|
||||
G05
|
||||
T1
|
||||
X6.56Y-2.74
|
||||
X6.6584Y-2.74
|
||||
X3.86Y-3.24
|
||||
X3.86Y-3.3384
|
||||
X5.3Y-1.12
|
||||
X5.3Y-1.2184
|
||||
T2
|
||||
X3.6Y-1.58
|
||||
X3.7Y-1.58
|
||||
T3
|
||||
X3.2Y-2.5
|
||||
X3.2Y-2.6
|
||||
X3.2Y-2.7
|
||||
X3.8Y-1.82
|
||||
X3.8Y-1.92
|
||||
X3.8Y-2.02
|
||||
X3.8Y-2.12
|
||||
X3.2Y-3.05
|
||||
X3.2Y-3.15
|
||||
X3.2Y-3.25
|
||||
X5.62Y-1.1
|
||||
X5.72Y-1.1
|
||||
X5.82Y-1.1
|
||||
X4.719Y-3.53
|
||||
X4.819Y-3.53
|
||||
X4.919Y-3.53
|
||||
X5.019Y-3.53
|
||||
X6.55Y-1.45
|
||||
X6.55Y-1.55
|
||||
X6.55Y-1.65
|
||||
X3.4Y-1.2
|
||||
X3.4Y-1.3
|
||||
X3.4Y-1.4
|
||||
X3.2Y-1.82
|
||||
X3.2Y-1.92
|
||||
X3.2Y-2.02
|
||||
X3.2Y-2.12
|
||||
X6.6Y-2.05
|
||||
X6.6Y-2.15
|
||||
X6.6Y-2.25
|
||||
X3.5Y-1.82
|
||||
X3.5Y-1.92
|
||||
X3.5Y-2.02
|
||||
X3.5Y-2.12
|
||||
X5.9Y-2.05
|
||||
X5.9Y-2.15
|
||||
X5.9Y-2.25
|
||||
X5.9Y-2.35
|
||||
X5.9Y-2.45
|
||||
X5.9Y-2.55
|
||||
X3.769Y-1.363
|
||||
X3.869Y-1.363
|
||||
X3.5Y-2.5
|
||||
X3.5Y-2.6
|
||||
X3.5Y-2.7
|
||||
X5.5Y-1.45
|
||||
X5.6Y-1.45
|
||||
X5.7Y-1.45
|
||||
X5.8Y-1.45
|
||||
X5.9Y-1.45
|
||||
X3.8Y-2.4
|
||||
X3.8Y-2.5
|
||||
X3.8Y-2.6
|
||||
X3.8Y-2.7
|
||||
X3.8Y-2.8
|
||||
X3.8Y-2.9
|
||||
X6.3Y-2.05
|
||||
X6.3Y-2.15
|
||||
X6.3Y-2.25
|
||||
X6.3Y-2.35
|
||||
X6.3Y-2.45
|
||||
X6.3Y-2.55
|
||||
X6.25Y-1.45
|
||||
X6.25Y-1.55
|
||||
X6.25Y-1.65
|
||||
X6.15Y-1.1
|
||||
X6.25Y-1.1
|
||||
X6.35Y-1.1
|
||||
T4
|
||||
X4.285Y-1.08
|
||||
X4.285Y-1.18
|
||||
X4.285Y-1.28
|
||||
X4.285Y-1.38
|
||||
X4.285Y-1.48
|
||||
X4.285Y-1.58
|
||||
X4.285Y-1.68
|
||||
X4.285Y-1.78
|
||||
X4.285Y-1.88
|
||||
X4.285Y-1.98
|
||||
X4.285Y-2.08
|
||||
X4.285Y-2.18
|
||||
X4.285Y-2.28
|
||||
X4.285Y-2.38
|
||||
X4.285Y-2.48
|
||||
X4.285Y-2.58
|
||||
X4.285Y-2.68
|
||||
X4.285Y-2.78
|
||||
X4.285Y-2.88
|
||||
X4.285Y-2.98
|
||||
X4.535Y-2.9709
|
||||
X4.635Y-2.9709
|
||||
X4.735Y-2.9709
|
||||
X4.985Y-1.08
|
||||
X4.985Y-1.18
|
||||
X4.985Y-1.28
|
||||
X4.985Y-1.38
|
||||
X4.985Y-1.48
|
||||
X4.985Y-1.58
|
||||
X4.985Y-1.68
|
||||
X4.985Y-1.78
|
||||
X4.985Y-1.88
|
||||
X4.985Y-1.98
|
||||
X4.985Y-2.08
|
||||
X4.985Y-2.18
|
||||
X4.985Y-2.28
|
||||
X4.985Y-2.38
|
||||
X4.985Y-2.48
|
||||
X4.985Y-2.58
|
||||
X4.985Y-2.68
|
||||
X4.985Y-2.78
|
||||
X4.985Y-2.88
|
||||
X4.985Y-2.98
|
||||
X5.75Y-2.9118
|
||||
X5.85Y-2.9118
|
||||
X5.95Y-2.9118
|
||||
X6.05Y-2.9118
|
||||
T5
|
||||
X5.373Y-1.7561
|
||||
X5.373Y-2.012
|
||||
X5.5502Y-1.7561
|
||||
X5.5502Y-2.012
|
||||
X4.05Y-3.575
|
||||
X4.05Y-3.7522
|
||||
X4.3059Y-3.575
|
||||
X4.3059Y-3.7522
|
||||
X3.4Y-3.575
|
||||
X3.4Y-3.7522
|
||||
X3.6559Y-3.575
|
||||
X3.6559Y-3.7522
|
||||
T6
|
||||
X4.5395Y-1.2044
|
||||
X4.7305Y-1.2044
|
||||
T7
|
||||
X4.5277Y-1.0851
|
||||
X4.7423Y-1.0851
|
||||
T8
|
||||
X5.4413Y-2.9315
|
||||
X5.4413Y-3.8685
|
||||
X6.3587Y-2.9315
|
||||
X6.3587Y-3.8685
|
||||
T9
|
||||
X6.65Y-1.15
|
||||
X3.05Y-3.85
|
||||
X6.65Y-3.85
|
||||
X3.05Y-1.15
|
||||
T0
|
||||
M30
|
||||
3
board/pico-dev/lib/MCU_RaspberryPi_and_Boards.dcm
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
EESchema-DOCLIB Version 2.0
|
||||
#
|
||||
#End Doc Library
|
||||
131
board/pico-dev/lib/MCU_RaspberryPi_and_Boards.lib
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
EESchema-LIBRARY Version 2.4
|
||||
#encoding utf-8
|
||||
#
|
||||
# Pico
|
||||
#
|
||||
DEF Pico U 0 40 Y Y 1 F N
|
||||
F0 "U" -550 1100 50 H V C CNN
|
||||
F1 "Pico" 0 750 50 H V C CNN
|
||||
F2 "RPi_Pico:RPi_Pico_SMD_TH" 0 0 50 V I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
T 0 0 850 50 0 0 0 "Raspberry Pi" Normal 0 C C
|
||||
S -600 1050 600 -1050 0 1 0 f
|
||||
X GPIO0 1 -700 950 100 R 50 50 1 1 B
|
||||
X GPIO7 10 -700 50 100 R 50 50 1 1 B
|
||||
X GPIO8 11 -700 -50 100 R 50 50 1 1 B
|
||||
X GPIO9 12 -700 -150 100 R 50 50 1 1 B
|
||||
X GND 13 -700 -250 100 R 50 50 1 1 W
|
||||
X GPIO10 14 -700 -350 100 R 50 50 1 1 B
|
||||
X GPIO11 15 -700 -450 100 R 50 50 1 1 B
|
||||
X GPIO12 16 -700 -550 100 R 50 50 1 1 B
|
||||
X GPIO13 17 -700 -650 100 R 50 50 1 1 B
|
||||
X GND 18 -700 -750 100 R 50 50 1 1 W
|
||||
X GPIO14 19 -700 -850 100 R 50 50 1 1 B
|
||||
X GPIO1 2 -700 850 100 R 50 50 1 1 B
|
||||
X GPIO15 20 -700 -950 100 R 50 50 1 1 B
|
||||
X GPIO16 21 700 -950 100 L 50 50 1 1 B
|
||||
X GPIO17 22 700 -850 100 L 50 50 1 1 B
|
||||
X GND 23 700 -750 100 L 50 50 1 1 W
|
||||
X GPIO18 24 700 -650 100 L 50 50 1 1 B
|
||||
X GPIO19 25 700 -550 100 L 50 50 1 1 B
|
||||
X GPIO20 26 700 -450 100 L 50 50 1 1 B
|
||||
X GPIO21 27 700 -350 100 L 50 50 1 1 B
|
||||
X GND 28 700 -250 100 L 50 50 1 1 W
|
||||
X GPIO22 29 700 -150 100 L 50 50 1 1 B
|
||||
X GND 3 -700 750 100 R 50 50 1 1 W
|
||||
X RUN 30 700 -50 100 L 50 50 1 1 I
|
||||
X GPIO26_ADC0 31 700 50 100 L 50 50 1 1 B
|
||||
X GPIO27_ADC1 32 700 150 100 L 50 50 1 1 B
|
||||
X AGND 33 700 250 100 L 50 50 1 1 W
|
||||
X GPIO28_ADC2 34 700 350 100 L 50 50 1 1 B
|
||||
X ADC_VREF 35 700 450 100 L 50 50 1 1 U
|
||||
X 3V3 36 700 550 100 L 50 50 1 1 U
|
||||
X 3V3_EN 37 700 650 100 L 50 50 1 1 I
|
||||
X GND 38 700 750 100 L 50 50 1 1 B
|
||||
X VSYS 39 700 850 100 L 50 50 1 1 U
|
||||
X GPIO2 4 -700 650 100 R 50 50 1 1 B
|
||||
X VBUS 40 700 950 100 L 50 50 1 1 U
|
||||
X SWCLK 41 -100 -1150 100 U 50 50 1 1 I
|
||||
X GND 42 0 -1150 100 U 50 50 1 1 W
|
||||
X SWDIO 43 100 -1150 100 U 50 50 1 1 B
|
||||
X GPIO3 5 -700 550 100 R 50 50 1 1 B
|
||||
X GPIO4 6 -700 450 100 R 50 50 1 1 B
|
||||
X GPIO5 7 -700 350 100 R 50 50 1 1 B
|
||||
X GND 8 -700 250 100 R 50 50 1 1 W
|
||||
X GPIO6 9 -700 150 100 R 50 50 1 1 B
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# RP2040
|
||||
#
|
||||
DEF RP2040 U 0 40 Y Y 1 F N
|
||||
F0 "U" -1150 1950 50 H V C CNN
|
||||
F1 "RP2040" 950 -1950 50 H V C CNN
|
||||
F2 "RP2040_minimal:RP2040-QFN-56" -750 0 50 H I C CNN
|
||||
F3 "" -750 0 50 H I C CNN
|
||||
DRAW
|
||||
T 0 0 200 100 0 0 0 "Raspberry Pi" Normal 0 C C
|
||||
T 0 0 0 100 0 0 0 RP2040 Normal 0 C C
|
||||
S 1150 1900 -1150 -1900 0 1 10 f
|
||||
X IOVDD 1 350 2000 100 D 50 50 1 1 W
|
||||
X IOVDD 10 250 2000 100 D 50 50 1 1 W
|
||||
X GPIO8 11 1250 500 100 L 50 50 1 1 B
|
||||
X GPIO9 12 1250 400 100 L 50 50 1 1 B
|
||||
X GPIO10 13 1250 300 100 L 50 50 1 1 B
|
||||
X GPIO11 14 1250 200 100 L 50 50 1 1 B
|
||||
X GPIO12 15 1250 100 100 L 50 50 1 1 B
|
||||
X GPIO13 16 1250 0 100 L 50 50 1 1 B
|
||||
X GPIO14 17 1250 -100 100 L 50 50 1 1 B
|
||||
X GPIO15 18 1250 -200 100 L 50 50 1 1 B
|
||||
X TESTEN 19 -500 -2000 100 U 50 50 1 1 P
|
||||
X GPIO0 2 1250 1300 100 L 50 50 1 1 B
|
||||
X XIN 20 -1250 -100 100 R 50 50 1 1 I
|
||||
X XOUT 21 -1250 -300 100 R 50 50 1 1 P
|
||||
X IOVDD 22 150 2000 100 D 50 50 1 1 W
|
||||
X DVDD 23 -700 2000 100 D 50 50 1 1 W
|
||||
X SWCLK 24 -1250 -1250 100 R 50 50 1 1 O
|
||||
X SWD 25 -1250 -1350 100 R 50 50 1 1 B
|
||||
X RUN 26 -1250 -800 100 R 50 50 1 1 I
|
||||
X GPIO16 27 1250 -300 100 L 50 50 1 1 B
|
||||
X GPIO17 28 1250 -400 100 L 50 50 1 1 B
|
||||
X GPIO18 29 1250 -500 100 L 50 50 1 1 B
|
||||
X GPIO1 3 1250 1200 100 L 50 50 1 1 B
|
||||
X GPIO19 30 1250 -600 100 L 50 50 1 1 B
|
||||
X GPIO20 31 1250 -700 100 L 50 50 1 1 B
|
||||
X GPIO21 32 1250 -800 100 L 50 50 1 1 B
|
||||
X IOVDD 33 50 2000 100 D 50 50 1 1 W
|
||||
X GPIO22 34 1250 -900 100 L 50 50 1 1 B
|
||||
X GPIO23 35 1250 -1000 100 L 50 50 1 1 B
|
||||
X GPIO24 36 1250 -1100 100 L 50 50 1 1 B
|
||||
X GPIO25 37 1250 -1200 100 L 50 50 1 1 B
|
||||
X GPIO26_ADC0 38 1250 -1400 100 L 50 50 1 1 B
|
||||
X GPIO27_ADC1 39 1250 -1500 100 L 50 50 1 1 B
|
||||
X GPIO2 4 1250 1100 100 L 50 50 1 1 B
|
||||
X GPIO28_ADC2 40 1250 -1600 100 L 50 50 1 1 B
|
||||
X GPIO29_ADC3 41 1250 -1700 100 L 50 50 1 1 B
|
||||
X IOVDD 42 -50 2000 100 D 50 50 1 1 W
|
||||
X ADC_AVDD 43 650 2000 100 D 50 50 1 1 W
|
||||
X VREG_IN 44 -350 2000 100 D 50 50 1 1 W
|
||||
X VREG_VOUT 45 -500 2000 100 D 50 50 1 1 w
|
||||
X USB_DM 46 1250 1600 100 L 50 50 1 1 B
|
||||
X USB_DP 47 1250 1700 100 L 50 50 1 1 B
|
||||
X USB_VDD 48 500 2000 100 D 50 50 1 1 W
|
||||
X IOVDD 49 -150 2000 100 D 50 50 1 1 W
|
||||
X GPIO3 5 1250 1000 100 L 50 50 1 1 B
|
||||
X DVDD 50 -800 2000 100 D 50 50 1 1 W
|
||||
X QSPI_SD3 51 -1250 800 100 R 50 50 1 1 B
|
||||
X QSPI_SCLK 52 -1250 650 100 R 50 50 1 1 O
|
||||
X QSPI_SD0 53 -1250 1100 100 R 50 50 1 1 B
|
||||
X QSPI_SD2 54 -1250 900 100 R 50 50 1 1 B
|
||||
X QSPI_SD1 55 -1250 1000 100 R 50 50 1 1 B
|
||||
X QSPI_SS 56 -1250 1250 100 R 50 50 1 1 B
|
||||
X GND 57 0 -2000 100 U 50 50 1 1 W
|
||||
X GPIO4 6 1250 900 100 L 50 50 1 1 B
|
||||
X GPIO5 7 1250 800 100 L 50 50 1 1 B
|
||||
X GPIO6 8 1250 700 100 L 50 50 1 1 B
|
||||
X GPIO7 9 1250 600 100 L 50 50 1 1 B
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
||||
9
board/pico-dev/lib/oled_ssd1306.dcm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
EESchema-DOCLIB Version 2.0
|
||||
#
|
||||
$CMP SSD1306_I2C
|
||||
D LCD 16x2 Alphanumeric gray backlight, 3 or 5 V VDD
|
||||
K display LCD dot-matrix
|
||||
F http://www.raystar-optronics.com/down.php?ProID=18
|
||||
$ENDCMP
|
||||
#
|
||||
#End Doc Library
|
||||
23
board/pico-dev/lib/oled_ssd1306.lib
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
EESchema-LIBRARY Version 2.4
|
||||
#encoding utf-8
|
||||
#
|
||||
# SSD1306_I2C
|
||||
#
|
||||
DEF SSD1306_I2C U 0 20 Y Y 1 F N
|
||||
F0 "U" -250 250 50 H V C CNN
|
||||
F1 "SSD1306_I2C" 100 250 50 H V L CNN
|
||||
F2 "Display:SSD1306" 350 -250 50 H I C CNN
|
||||
F3 "" 100 -100 50 H I C CNN
|
||||
$FPLIST
|
||||
*SSD1306_I2C*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -300 200 300 -200 0 1 10 f
|
||||
X GND 1 0 -300 100 U 50 50 1 1 W
|
||||
X VDD 2 0 300 100 D 50 50 1 1 W
|
||||
X SCL 3 -400 100 100 R 50 50 1 1 I
|
||||
X SDA 4 -400 -100 100 R 50 50 1 1 B
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
||||
398
board/pico-dev/pico-dev-cache.lib
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
EESchema-LIBRARY Version 2.4
|
||||
#encoding utf-8
|
||||
#
|
||||
# Connector_Conn_01x02_Male
|
||||
#
|
||||
DEF Connector_Conn_01x02_Male J 0 40 Y N 1 F N
|
||||
F0 "J" 0 100 50 H V C CNN
|
||||
F1 "Connector_Conn_01x02_Male" 0 -200 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S 34 -95 0 -105 1 1 6 F
|
||||
S 34 5 0 -5 1 1 6 F
|
||||
P 2 1 1 6 50 -100 34 -100 N
|
||||
P 2 1 1 6 50 0 34 0 N
|
||||
X Pin_1 1 200 0 150 L 50 50 1 1 P
|
||||
X Pin_2 2 200 -100 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Conn_01x03_Male
|
||||
#
|
||||
DEF Connector_Conn_01x03_Male J 0 40 Y N 1 F N
|
||||
F0 "J" 0 200 50 H V C CNN
|
||||
F1 "Connector_Conn_01x03_Male" 0 -200 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S 34 -95 0 -105 1 1 6 F
|
||||
S 34 5 0 -5 1 1 6 F
|
||||
S 34 105 0 95 1 1 6 F
|
||||
P 2 1 1 6 50 -100 34 -100 N
|
||||
P 2 1 1 6 50 0 34 0 N
|
||||
P 2 1 1 6 50 100 34 100 N
|
||||
X Pin_1 1 200 100 150 L 50 50 1 1 P
|
||||
X Pin_2 2 200 0 150 L 50 50 1 1 P
|
||||
X Pin_3 3 200 -100 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Conn_01x04_Male
|
||||
#
|
||||
DEF Connector_Conn_01x04_Male J 0 40 Y N 1 F N
|
||||
F0 "J" 0 200 50 H V C CNN
|
||||
F1 "Connector_Conn_01x04_Male" 0 -300 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S 34 -195 0 -205 1 1 6 F
|
||||
S 34 -95 0 -105 1 1 6 F
|
||||
S 34 5 0 -5 1 1 6 F
|
||||
S 34 105 0 95 1 1 6 F
|
||||
P 2 1 1 6 50 -200 34 -200 N
|
||||
P 2 1 1 6 50 -100 34 -100 N
|
||||
P 2 1 1 6 50 0 34 0 N
|
||||
P 2 1 1 6 50 100 34 100 N
|
||||
X Pin_1 1 200 100 150 L 50 50 1 1 P
|
||||
X Pin_2 2 200 0 150 L 50 50 1 1 P
|
||||
X Pin_3 3 200 -100 150 L 50 50 1 1 P
|
||||
X Pin_4 4 200 -200 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Conn_01x05_Male
|
||||
#
|
||||
DEF Connector_Conn_01x05_Male J 0 40 Y N 1 F N
|
||||
F0 "J" 0 300 50 H V C CNN
|
||||
F1 "Connector_Conn_01x05_Male" 0 -300 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S 34 -195 0 -205 1 1 6 F
|
||||
S 34 -95 0 -105 1 1 6 F
|
||||
S 34 5 0 -5 1 1 6 F
|
||||
S 34 105 0 95 1 1 6 F
|
||||
S 34 205 0 195 1 1 6 F
|
||||
P 2 1 1 6 50 -200 34 -200 N
|
||||
P 2 1 1 6 50 -100 34 -100 N
|
||||
P 2 1 1 6 50 0 34 0 N
|
||||
P 2 1 1 6 50 100 34 100 N
|
||||
P 2 1 1 6 50 200 34 200 N
|
||||
X Pin_1 1 200 200 150 L 50 50 1 1 P
|
||||
X Pin_2 2 200 100 150 L 50 50 1 1 P
|
||||
X Pin_3 3 200 0 150 L 50 50 1 1 P
|
||||
X Pin_4 4 200 -100 150 L 50 50 1 1 P
|
||||
X Pin_5 5 200 -200 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Conn_01x06_Female
|
||||
#
|
||||
DEF Connector_Conn_01x06_Female J 0 40 Y N 1 F N
|
||||
F0 "J" 0 300 50 H V C CNN
|
||||
F1 "Connector_Conn_01x06_Female" 0 -400 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
A 0 -300 20 901 -901 1 1 6 N 0 -280 0 -320
|
||||
A 0 -200 20 901 -901 1 1 6 N 0 -180 0 -220
|
||||
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||
A 0 100 20 901 -901 1 1 6 N 0 120 0 80
|
||||
A 0 200 20 901 -901 1 1 6 N 0 220 0 180
|
||||
P 2 1 1 6 -50 -300 -20 -300 N
|
||||
P 2 1 1 6 -50 -200 -20 -200 N
|
||||
P 2 1 1 6 -50 -100 -20 -100 N
|
||||
P 2 1 1 6 -50 0 -20 0 N
|
||||
P 2 1 1 6 -50 100 -20 100 N
|
||||
P 2 1 1 6 -50 200 -20 200 N
|
||||
X Pin_1 1 -200 200 150 R 50 50 1 1 P
|
||||
X Pin_2 2 -200 100 150 R 50 50 1 1 P
|
||||
X Pin_3 3 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_4 4 -200 -100 150 R 50 50 1 1 P
|
||||
X Pin_5 5 -200 -200 150 R 50 50 1 1 P
|
||||
X Pin_6 6 -200 -300 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_CP
|
||||
#
|
||||
DEF Device_CP C 0 10 N Y 1 F N
|
||||
F0 "C" 25 100 50 H V L CNN
|
||||
F1 "Device_CP" 25 -100 50 H V L CNN
|
||||
F2 "" 38 -150 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
CP_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -90 20 -90 40 0 1 0 N
|
||||
S -90 20 90 20 0 1 0 N
|
||||
S 90 -20 -90 -40 0 1 0 F
|
||||
S 90 40 -90 40 0 1 0 N
|
||||
S 90 40 90 20 0 1 0 N
|
||||
P 2 0 1 0 -70 90 -30 90 N
|
||||
P 2 0 1 0 -50 110 -50 70 N
|
||||
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||
X ~ 2 0 -150 110 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_D_Schottky
|
||||
#
|
||||
DEF Device_D_Schottky D 0 40 N N 1 F N
|
||||
F0 "D" 0 100 50 H V C CNN
|
||||
F1 "Device_D_Schottky" 0 -100 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
TO-???*
|
||||
*_Diode_*
|
||||
*SingleDiode*
|
||||
D_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
P 2 0 1 0 50 0 -50 0 N
|
||||
P 4 0 1 8 50 50 50 -50 -50 0 50 50 N
|
||||
P 6 0 1 8 -75 25 -75 50 -50 50 -50 -50 -25 -50 -25 -25 N
|
||||
X K 1 -150 0 100 R 50 50 1 1 P
|
||||
X A 2 150 0 100 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_LED
|
||||
#
|
||||
DEF Device_LED D 0 40 N N 1 F N
|
||||
F0 "D" 0 100 50 H V C CNN
|
||||
F1 "Device_LED" 0 -100 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
LED*
|
||||
LED_SMD:*
|
||||
LED_THT:*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
P 2 0 1 8 -50 -50 -50 50 N
|
||||
P 2 0 1 0 -50 0 50 0 N
|
||||
P 4 0 1 8 50 -50 50 50 -50 0 50 -50 N
|
||||
P 5 0 1 0 -120 -30 -180 -90 -150 -90 -180 -90 -180 -60 N
|
||||
P 5 0 1 0 -70 -30 -130 -90 -100 -90 -130 -90 -130 -60 N
|
||||
X K 1 -150 0 100 R 50 50 1 1 P
|
||||
X A 2 150 0 100 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_R
|
||||
#
|
||||
DEF Device_R R 0 0 N Y 1 F N
|
||||
F0 "R" 80 0 50 V V C CNN
|
||||
F1 "Device_R" 0 0 50 V V C CNN
|
||||
F2 "" -70 0 50 V I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
R_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -40 -100 40 100 0 1 10 N
|
||||
X ~ 1 0 150 50 D 50 50 1 1 P
|
||||
X ~ 2 0 -150 50 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# MCU_RaspberryPi_and_Boards_Pico
|
||||
#
|
||||
DEF MCU_RaspberryPi_and_Boards_Pico U 0 40 Y Y 1 F N
|
||||
F0 "U" -550 1100 50 H V C CNN
|
||||
F1 "MCU_RaspberryPi_and_Boards_Pico" 0 750 50 H V C CNN
|
||||
F2 "RPi_Pico:RPi_Pico_SMD_TH" 0 0 50 V I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
T 0 0 850 50 0 0 0 "Raspberry Pi" Normal 0 C C
|
||||
S -600 1050 600 -1050 0 1 0 f
|
||||
X GPIO0 1 -700 950 100 R 50 50 1 1 B
|
||||
X GPIO7 10 -700 50 100 R 50 50 1 1 B
|
||||
X GPIO8 11 -700 -50 100 R 50 50 1 1 B
|
||||
X GPIO9 12 -700 -150 100 R 50 50 1 1 B
|
||||
X GND 13 -700 -250 100 R 50 50 1 1 W
|
||||
X GPIO10 14 -700 -350 100 R 50 50 1 1 B
|
||||
X GPIO11 15 -700 -450 100 R 50 50 1 1 B
|
||||
X GPIO12 16 -700 -550 100 R 50 50 1 1 B
|
||||
X GPIO13 17 -700 -650 100 R 50 50 1 1 B
|
||||
X GND 18 -700 -750 100 R 50 50 1 1 W
|
||||
X GPIO14 19 -700 -850 100 R 50 50 1 1 B
|
||||
X GPIO1 2 -700 850 100 R 50 50 1 1 B
|
||||
X GPIO15 20 -700 -950 100 R 50 50 1 1 B
|
||||
X GPIO16 21 700 -950 100 L 50 50 1 1 B
|
||||
X GPIO17 22 700 -850 100 L 50 50 1 1 B
|
||||
X GND 23 700 -750 100 L 50 50 1 1 W
|
||||
X GPIO18 24 700 -650 100 L 50 50 1 1 B
|
||||
X GPIO19 25 700 -550 100 L 50 50 1 1 B
|
||||
X GPIO20 26 700 -450 100 L 50 50 1 1 B
|
||||
X GPIO21 27 700 -350 100 L 50 50 1 1 B
|
||||
X GND 28 700 -250 100 L 50 50 1 1 W
|
||||
X GPIO22 29 700 -150 100 L 50 50 1 1 B
|
||||
X GND 3 -700 750 100 R 50 50 1 1 W
|
||||
X RUN 30 700 -50 100 L 50 50 1 1 I
|
||||
X GPIO26_ADC0 31 700 50 100 L 50 50 1 1 B
|
||||
X GPIO27_ADC1 32 700 150 100 L 50 50 1 1 B
|
||||
X AGND 33 700 250 100 L 50 50 1 1 W
|
||||
X GPIO28_ADC2 34 700 350 100 L 50 50 1 1 B
|
||||
X ADC_VREF 35 700 450 100 L 50 50 1 1 U
|
||||
X 3V3 36 700 550 100 L 50 50 1 1 U
|
||||
X 3V3_EN 37 700 650 100 L 50 50 1 1 I
|
||||
X GND 38 700 750 100 L 50 50 1 1 B
|
||||
X VSYS 39 700 850 100 L 50 50 1 1 U
|
||||
X GPIO2 4 -700 650 100 R 50 50 1 1 B
|
||||
X VBUS 40 700 950 100 L 50 50 1 1 U
|
||||
X SWCLK 41 -100 -1150 100 U 50 50 1 1 I
|
||||
X GND 42 0 -1150 100 U 50 50 1 1 W
|
||||
X SWDIO 43 100 -1150 100 U 50 50 1 1 B
|
||||
X GPIO3 5 -700 550 100 R 50 50 1 1 B
|
||||
X GPIO4 6 -700 450 100 R 50 50 1 1 B
|
||||
X GPIO5 7 -700 350 100 R 50 50 1 1 B
|
||||
X GND 8 -700 250 100 R 50 50 1 1 W
|
||||
X GPIO6 9 -700 150 100 R 50 50 1 1 B
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Mechanical_MountingHole
|
||||
#
|
||||
DEF Mechanical_MountingHole H 0 40 Y Y 1 F N
|
||||
F0 "H" 0 200 50 H V C CNN
|
||||
F1 "Mechanical_MountingHole" 0 125 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
MountingHole*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
C 0 0 50 0 1 50 N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Switch_SW_Push
|
||||
#
|
||||
DEF Switch_SW_Push SW 0 40 N N 1 F N
|
||||
F0 "SW" 50 100 50 H V L CNN
|
||||
F1 "Switch_SW_Push" 0 -60 50 H V C CNN
|
||||
F2 "" 0 200 50 H I C CNN
|
||||
F3 "" 0 200 50 H I C CNN
|
||||
DRAW
|
||||
C -80 0 20 0 1 0 N
|
||||
C 80 0 20 0 1 0 N
|
||||
P 2 0 1 0 0 50 0 120 N
|
||||
P 2 0 1 0 100 50 -100 50 N
|
||||
X 1 1 -200 0 100 R 50 50 0 1 P
|
||||
X 2 2 200 0 100 L 50 50 0 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# oled_ssd1306_SSD1306_I2C
|
||||
#
|
||||
DEF oled_ssd1306_SSD1306_I2C U 0 20 Y Y 1 F N
|
||||
F0 "U" -250 250 50 H V C CNN
|
||||
F1 "oled_ssd1306_SSD1306_I2C" 100 250 50 H V L CNN
|
||||
F2 "Display:SSD1306" 350 -250 50 H I C CNN
|
||||
F3 "" 100 -100 50 H I C CNN
|
||||
$FPLIST
|
||||
*SSD1306_I2C*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -300 200 300 -200 0 1 10 f
|
||||
X GND 1 0 -300 100 U 50 50 1 1 W
|
||||
X VDD 2 0 300 100 D 50 50 1 1 W
|
||||
X SCL 3 -400 100 100 R 50 50 1 1 I
|
||||
X SDA 4 -400 -100 100 R 50 50 1 1 B
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_+3.3V
|
||||
#
|
||||
DEF power_+3.3V #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_+3.3V" 0 140 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
ALIAS +3.3V
|
||||
DRAW
|
||||
P 2 0 1 0 -30 50 0 100 N
|
||||
P 2 0 1 0 0 0 0 100 N
|
||||
P 2 0 1 0 0 100 30 50 N
|
||||
X +3V3 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_+5V
|
||||
#
|
||||
DEF power_+5V #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_+5V" 0 140 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 2 0 1 0 -30 50 0 100 N
|
||||
P 2 0 1 0 0 0 0 100 N
|
||||
P 2 0 1 0 0 100 30 50 N
|
||||
X +5V 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_+5VD
|
||||
#
|
||||
DEF power_+5VD #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_+5VD" 0 140 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 2 0 1 0 -30 50 0 100 N
|
||||
P 2 0 1 0 0 0 0 100 N
|
||||
P 2 0 1 0 0 100 30 50 N
|
||||
X +5VD 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_GND
|
||||
#
|
||||
DEF power_GND #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -250 50 H I C CNN
|
||||
F1 "power_GND" 0 -150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_PWR_FLAG
|
||||
#
|
||||
DEF power_PWR_FLAG #FLG 0 0 N N 1 F P
|
||||
F0 "#FLG" 0 75 50 H I C CNN
|
||||
F1 "power_PWR_FLAG" 0 150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 50 -40 75 0 100 40 75 0 50 N
|
||||
X pwr 1 0 0 0 U 50 50 0 0 w
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
||||
4035
board/pico-dev/pico-dev.kicad_pcb
Normal file
33
board/pico-dev/pico-dev.pro
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
update=22/05/2015 07:44:53
|
||||
version=1
|
||||
last_client=kicad
|
||||
[general]
|
||||
version=1
|
||||
RootSch=
|
||||
BoardNm=
|
||||
[pcbnew]
|
||||
version=1
|
||||
LastNetListRead=
|
||||
UseCmpFile=1
|
||||
PadDrill=0.600000000000
|
||||
PadDrillOvalY=0.600000000000
|
||||
PadSizeH=1.500000000000
|
||||
PadSizeV=1.500000000000
|
||||
PcbTextSizeV=1.500000000000
|
||||
PcbTextSizeH=1.500000000000
|
||||
PcbTextThickness=0.300000000000
|
||||
ModuleTextSizeV=1.000000000000
|
||||
ModuleTextSizeH=1.000000000000
|
||||
ModuleTextSizeThickness=0.150000000000
|
||||
SolderMaskClearance=0.000000000000
|
||||
SolderMaskMinWidth=0.000000000000
|
||||
DrawSegmentWidth=0.200000000000
|
||||
BoardOutlineThickness=0.100000000000
|
||||
ModuleOutlineThickness=0.150000000000
|
||||
[cvpcb]
|
||||
version=1
|
||||
NetIExt=net
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
[eeschema/libraries]
|
||||
1533
board/pico-dev/pico-dev.sch
Normal file
23191
board/pico-dev/step/Pico-R3.step
Normal file
4
board/pico-dev/sym-lib-table
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(sym_lib_table
|
||||
(lib (name MCU_RaspberryPi_and_Boards)(type Legacy)(uri ${KIPRJMOD}/lib/MCU_RaspberryPi_and_Boards.lib)(options "")(descr ""))
|
||||
(lib (name oled_ssd1306)(type Legacy)(uri ${KIPRJMOD}/lib/oled_ssd1306.lib)(options "")(descr ""))
|
||||
)
|
||||
0
examples/__init__.py
Normal file
0
examples/external/__init__.py
vendored
Normal file
614
examples/external/adafruit_vl53l0x.py
vendored
Normal file
|
|
@ -0,0 +1,614 @@
|
|||
# From https://github.com/adafruit/Adafruit_CircuitPython_VL53L0X which is originally licensed : see below.
|
||||
# Minor changes to work on micropython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# SPDX-FileCopyrightText: 2017 Tony DiCola for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Caution: this version is modified to work with u2if python library
|
||||
|
||||
"""
|
||||
`adafruit_vl53l0x`
|
||||
====================================================
|
||||
|
||||
CircuitPython driver for the VL53L0X distance sensor. This code is adapted
|
||||
from the pololu driver here:
|
||||
https://github.com/pololu/vl53l0x-arduino
|
||||
|
||||
See usage in the examples/vl53l0x_simpletest.py file.
|
||||
|
||||
* Author(s): Tony DiCola
|
||||
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
**Hardware:**
|
||||
|
||||
* Adafruit `VL53L0X Time of Flight Distance Sensor - ~30 to 1000mm
|
||||
<https://www.adafruit.com/product/3317>`_ (Product ID: 3317)
|
||||
|
||||
**Software and Dependencies:**
|
||||
|
||||
* Adafruit CircuitPython firmware for the ESP8622 and M0-based boards:
|
||||
https://github.com/adafruit/circuitpython/releases
|
||||
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
|
||||
"""
|
||||
import math
|
||||
import time
|
||||
|
||||
#import adafruit_bus_device.i2c_device as i2c_device
|
||||
from micropython import const
|
||||
|
||||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_VL53L0X.git"
|
||||
|
||||
# Configuration constants:
|
||||
_SYSRANGE_START = const(0x00)
|
||||
_SYSTEM_THRESH_HIGH = const(0x0C)
|
||||
_SYSTEM_THRESH_LOW = const(0x0E)
|
||||
_SYSTEM_SEQUENCE_CONFIG = const(0x01)
|
||||
_SYSTEM_RANGE_CONFIG = const(0x09)
|
||||
_SYSTEM_INTERMEASUREMENT_PERIOD = const(0x04)
|
||||
_SYSTEM_INTERRUPT_CONFIG_GPIO = const(0x0A)
|
||||
_GPIO_HV_MUX_ACTIVE_HIGH = const(0x84)
|
||||
_SYSTEM_INTERRUPT_CLEAR = const(0x0B)
|
||||
_RESULT_INTERRUPT_STATUS = const(0x13)
|
||||
_RESULT_RANGE_STATUS = const(0x14)
|
||||
_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN = const(0xBC)
|
||||
_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN = const(0xC0)
|
||||
_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF = const(0xD0)
|
||||
_RESULT_CORE_RANGING_TOTAL_EVENTS_REF = const(0xD4)
|
||||
_RESULT_PEAK_SIGNAL_RATE_REF = const(0xB6)
|
||||
_ALGO_PART_TO_PART_RANGE_OFFSET_MM = const(0x28)
|
||||
_I2C_SLAVE_DEVICE_ADDRESS = const(0x8A)
|
||||
_MSRC_CONFIG_CONTROL = const(0x60)
|
||||
_PRE_RANGE_CONFIG_MIN_SNR = const(0x27)
|
||||
_PRE_RANGE_CONFIG_VALID_PHASE_LOW = const(0x56)
|
||||
_PRE_RANGE_CONFIG_VALID_PHASE_HIGH = const(0x57)
|
||||
_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT = const(0x64)
|
||||
_FINAL_RANGE_CONFIG_MIN_SNR = const(0x67)
|
||||
_FINAL_RANGE_CONFIG_VALID_PHASE_LOW = const(0x47)
|
||||
_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH = const(0x48)
|
||||
_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT = const(0x44)
|
||||
_PRE_RANGE_CONFIG_SIGMA_THRESH_HI = const(0x61)
|
||||
_PRE_RANGE_CONFIG_SIGMA_THRESH_LO = const(0x62)
|
||||
_PRE_RANGE_CONFIG_VCSEL_PERIOD = const(0x50)
|
||||
_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI = const(0x51)
|
||||
_PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO = const(0x52)
|
||||
_SYSTEM_HISTOGRAM_BIN = const(0x81)
|
||||
_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT = const(0x33)
|
||||
_HISTOGRAM_CONFIG_READOUT_CTRL = const(0x55)
|
||||
_FINAL_RANGE_CONFIG_VCSEL_PERIOD = const(0x70)
|
||||
_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI = const(0x71)
|
||||
_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO = const(0x72)
|
||||
_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS = const(0x20)
|
||||
_MSRC_CONFIG_TIMEOUT_MACROP = const(0x46)
|
||||
_SOFT_RESET_GO2_SOFT_RESET_N = const(0xBF)
|
||||
_IDENTIFICATION_MODEL_ID = const(0xC0)
|
||||
_IDENTIFICATION_REVISION_ID = const(0xC2)
|
||||
_OSC_CALIBRATE_VAL = const(0xF8)
|
||||
_GLOBAL_CONFIG_VCSEL_WIDTH = const(0x32)
|
||||
_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 = const(0xB0)
|
||||
_GLOBAL_CONFIG_SPAD_ENABLES_REF_1 = const(0xB1)
|
||||
_GLOBAL_CONFIG_SPAD_ENABLES_REF_2 = const(0xB2)
|
||||
_GLOBAL_CONFIG_SPAD_ENABLES_REF_3 = const(0xB3)
|
||||
_GLOBAL_CONFIG_SPAD_ENABLES_REF_4 = const(0xB4)
|
||||
_GLOBAL_CONFIG_SPAD_ENABLES_REF_5 = const(0xB5)
|
||||
_GLOBAL_CONFIG_REF_EN_START_SELECT = const(0xB6)
|
||||
_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD = const(0x4E)
|
||||
_DYNAMIC_SPAD_REF_EN_START_OFFSET = const(0x4F)
|
||||
_POWER_MANAGEMENT_GO1_POWER_FORCE = const(0x80)
|
||||
_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV = const(0x89)
|
||||
_ALGO_PHASECAL_LIM = const(0x30)
|
||||
_ALGO_PHASECAL_CONFIG_TIMEOUT = const(0x30)
|
||||
_VCSEL_PERIOD_PRE_RANGE = const(0)
|
||||
_VCSEL_PERIOD_FINAL_RANGE = const(1)
|
||||
|
||||
|
||||
def _decode_timeout(val):
|
||||
# format: "(LSByte * 2^MSByte) + 1"
|
||||
return float(val & 0xFF) * math.pow(2.0, ((val & 0xFF00) >> 8)) + 1
|
||||
|
||||
|
||||
def _encode_timeout(timeout_mclks):
|
||||
# format: "(LSByte * 2^MSByte) + 1"
|
||||
timeout_mclks = int(timeout_mclks) & 0xFFFF
|
||||
ls_byte = 0
|
||||
ms_byte = 0
|
||||
if timeout_mclks > 0:
|
||||
ls_byte = timeout_mclks - 1
|
||||
while ls_byte > 255:
|
||||
ls_byte >>= 1
|
||||
ms_byte += 1
|
||||
return ((ms_byte << 8) | (ls_byte & 0xFF)) & 0xFFFF
|
||||
return 0
|
||||
|
||||
|
||||
def _timeout_mclks_to_microseconds(timeout_period_mclks, vcsel_period_pclks):
|
||||
macro_period_ns = ((2304 * (vcsel_period_pclks) * 1655) + 500) // 1000
|
||||
return ((timeout_period_mclks * macro_period_ns) + (macro_period_ns // 2)) // 1000
|
||||
|
||||
|
||||
def _timeout_microseconds_to_mclks(timeout_period_us, vcsel_period_pclks):
|
||||
macro_period_ns = ((2304 * (vcsel_period_pclks) * 1655) + 500) // 1000
|
||||
return ((timeout_period_us * 1000) + (macro_period_ns // 2)) // macro_period_ns
|
||||
|
||||
|
||||
class VL53L0X:
|
||||
"""Driver for the VL53L0X distance sensor."""
|
||||
|
||||
# Class-level buffer for reading and writing data with the sensor.
|
||||
# This reduces memory allocations but means the code is not re-entrant or
|
||||
# thread safe!
|
||||
_BUFFER = bytearray(3)
|
||||
|
||||
def __init__(self, i2c, address=41, io_timeout_s=0):
|
||||
# pylint: disable=too-many-statements
|
||||
#self._i2c = i2c
|
||||
#self._device = i2c_device.I2CDevice(i2c, address)
|
||||
self._device = i2c
|
||||
self._address = address
|
||||
self.io_timeout_s = io_timeout_s
|
||||
# Check identification registers for expected values.
|
||||
# From section 3.2 of the datasheet.
|
||||
if (
|
||||
self._read_u8(0xC0) != 0xEE
|
||||
or self._read_u8(0xC1) != 0xAA
|
||||
or self._read_u8(0xC2) != 0x10
|
||||
):
|
||||
raise RuntimeError(
|
||||
"Failed to find expected ID register values. Check wiring!"
|
||||
)
|
||||
# Initialize access to the sensor. This is based on the logic from:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
|
||||
# Set I2C standard mode.
|
||||
for pair in ((0x88, 0x00), (0x80, 0x01), (0xFF, 0x01), (0x00, 0x00)):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
self._stop_variable = self._read_u8(0x91)
|
||||
for pair in ((0x00, 0x01), (0xFF, 0x00), (0x80, 0x00)):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
# disable SIGNAL_RATE_MSRC (bit 1) and SIGNAL_RATE_PRE_RANGE (bit 4)
|
||||
# limit checks
|
||||
config_control = self._read_u8(_MSRC_CONFIG_CONTROL) | 0x12
|
||||
self._write_u8(_MSRC_CONFIG_CONTROL, config_control)
|
||||
# set final range signal rate limit to 0.25 MCPS (million counts per
|
||||
# second)
|
||||
self.signal_rate_limit = 0.25
|
||||
self._write_u8(_SYSTEM_SEQUENCE_CONFIG, 0xFF)
|
||||
spad_count, spad_is_aperture = self._get_spad_info()
|
||||
# The SPAD map (RefGoodSpadMap) is read by
|
||||
# VL53L0X_get_info_from_device() in the API, but the same data seems to
|
||||
# be more easily readable from GLOBAL_CONFIG_SPAD_ENABLES_REF_0 through
|
||||
# _6, so read it from there.
|
||||
ref_spad_map = bytearray(7)
|
||||
ref_spad_map[0] = _GLOBAL_CONFIG_SPAD_ENABLES_REF_0
|
||||
#with self._device:
|
||||
# self._device.write(ref_spad_map, end=1)
|
||||
# self._device.readinto(ref_spad_map, start=1)
|
||||
self._device.writeto(self._address, bytes([ref_spad_map[0]]))
|
||||
res = self._device.readfrom(self._address, 6)
|
||||
for i in range(len(res)):
|
||||
ref_spad_map[i+1] = res[i]
|
||||
|
||||
for pair in (
|
||||
(0xFF, 0x01),
|
||||
(_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00),
|
||||
(_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C),
|
||||
(0xFF, 0x00),
|
||||
(_GLOBAL_CONFIG_REF_EN_START_SELECT, 0xB4),
|
||||
):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
|
||||
first_spad_to_enable = 12 if spad_is_aperture else 0
|
||||
spads_enabled = 0
|
||||
for i in range(48):
|
||||
if i < first_spad_to_enable or spads_enabled == spad_count:
|
||||
# This bit is lower than the first one that should be enabled,
|
||||
# or (reference_spad_count) bits have already been enabled, so
|
||||
# zero this bit.
|
||||
ref_spad_map[1 + (i // 8)] &= ~(1 << (i % 8))
|
||||
elif (ref_spad_map[1 + (i // 8)] >> (i % 8)) & 0x1 > 0:
|
||||
spads_enabled += 1
|
||||
#with self._device:
|
||||
# self._device.write(ref_spad_map)
|
||||
self._device.writeto(self._address, ref_spad_map)
|
||||
for pair in (
|
||||
(0xFF, 0x01),
|
||||
(0x00, 0x00),
|
||||
(0xFF, 0x00),
|
||||
(0x09, 0x00),
|
||||
(0x10, 0x00),
|
||||
(0x11, 0x00),
|
||||
(0x24, 0x01),
|
||||
(0x25, 0xFF),
|
||||
(0x75, 0x00),
|
||||
(0xFF, 0x01),
|
||||
(0x4E, 0x2C),
|
||||
(0x48, 0x00),
|
||||
(0x30, 0x20),
|
||||
(0xFF, 0x00),
|
||||
(0x30, 0x09),
|
||||
(0x54, 0x00),
|
||||
(0x31, 0x04),
|
||||
(0x32, 0x03),
|
||||
(0x40, 0x83),
|
||||
(0x46, 0x25),
|
||||
(0x60, 0x00),
|
||||
(0x27, 0x00),
|
||||
(0x50, 0x06),
|
||||
(0x51, 0x00),
|
||||
(0x52, 0x96),
|
||||
(0x56, 0x08),
|
||||
(0x57, 0x30),
|
||||
(0x61, 0x00),
|
||||
(0x62, 0x00),
|
||||
(0x64, 0x00),
|
||||
(0x65, 0x00),
|
||||
(0x66, 0xA0),
|
||||
(0xFF, 0x01),
|
||||
(0x22, 0x32),
|
||||
(0x47, 0x14),
|
||||
(0x49, 0xFF),
|
||||
(0x4A, 0x00),
|
||||
(0xFF, 0x00),
|
||||
(0x7A, 0x0A),
|
||||
(0x7B, 0x00),
|
||||
(0x78, 0x21),
|
||||
(0xFF, 0x01),
|
||||
(0x23, 0x34),
|
||||
(0x42, 0x00),
|
||||
(0x44, 0xFF),
|
||||
(0x45, 0x26),
|
||||
(0x46, 0x05),
|
||||
(0x40, 0x40),
|
||||
(0x0E, 0x06),
|
||||
(0x20, 0x1A),
|
||||
(0x43, 0x40),
|
||||
(0xFF, 0x00),
|
||||
(0x34, 0x03),
|
||||
(0x35, 0x44),
|
||||
(0xFF, 0x01),
|
||||
(0x31, 0x04),
|
||||
(0x4B, 0x09),
|
||||
(0x4C, 0x05),
|
||||
(0x4D, 0x04),
|
||||
(0xFF, 0x00),
|
||||
(0x44, 0x00),
|
||||
(0x45, 0x20),
|
||||
(0x47, 0x08),
|
||||
(0x48, 0x28),
|
||||
(0x67, 0x00),
|
||||
(0x70, 0x04),
|
||||
(0x71, 0x01),
|
||||
(0x72, 0xFE),
|
||||
(0x76, 0x00),
|
||||
(0x77, 0x00),
|
||||
(0xFF, 0x01),
|
||||
(0x0D, 0x01),
|
||||
(0xFF, 0x00),
|
||||
(0x80, 0x01),
|
||||
(0x01, 0xF8),
|
||||
(0xFF, 0x01),
|
||||
(0x8E, 0x01),
|
||||
(0x00, 0x01),
|
||||
(0xFF, 0x00),
|
||||
(0x80, 0x00),
|
||||
):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
|
||||
self._write_u8(_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x04)
|
||||
gpio_hv_mux_active_high = self._read_u8(_GPIO_HV_MUX_ACTIVE_HIGH)
|
||||
self._write_u8(
|
||||
_GPIO_HV_MUX_ACTIVE_HIGH, gpio_hv_mux_active_high & ~0x10
|
||||
) # active low
|
||||
self._write_u8(_SYSTEM_INTERRUPT_CLEAR, 0x01)
|
||||
self._measurement_timing_budget_us = self.measurement_timing_budget
|
||||
self._write_u8(_SYSTEM_SEQUENCE_CONFIG, 0xE8)
|
||||
self.measurement_timing_budget = self._measurement_timing_budget_us
|
||||
self._write_u8(_SYSTEM_SEQUENCE_CONFIG, 0x01)
|
||||
self._perform_single_ref_calibration(0x40)
|
||||
self._write_u8(_SYSTEM_SEQUENCE_CONFIG, 0x02)
|
||||
self._perform_single_ref_calibration(0x00)
|
||||
# "restore the previous Sequence Config"
|
||||
self._write_u8(_SYSTEM_SEQUENCE_CONFIG, 0xE8)
|
||||
|
||||
def _read_u8(self, address):
|
||||
# Read an 8-bit unsigned value from the specified 8-bit address.
|
||||
# with self._device:
|
||||
# self._BUFFER[0] = address & 0xFF
|
||||
# self._device.write(self._BUFFER, end=1)
|
||||
# self._device.readinto(self._BUFFER, end=1)
|
||||
return self._device.readfrom_mem(self._address, address & 0xFF, 1)[0]
|
||||
|
||||
def _read_u16(self, address):
|
||||
# Read a 16-bit BE unsigned value from the specified 8-bit address.
|
||||
# with self._device:
|
||||
# self._BUFFER[0] = address & 0xFF
|
||||
# self._device.write(self._BUFFER, end=1)
|
||||
# self._device.readinto(self._BUFFER)
|
||||
#return (self._BUFFER[0] << 8) | self._BUFFER[1]
|
||||
buf = self._device.readfrom_mem(self._address, address & 0xFF, 2)
|
||||
return (buf[0] << 8) | buf[1]
|
||||
|
||||
def _write_u8(self, address, val):
|
||||
# Write an 8-bit unsigned value to the specified 8-bit address.
|
||||
# with self._device:
|
||||
# self._BUFFER[0] = address & 0xFF
|
||||
# self._BUFFER[1] = val & 0xFF
|
||||
# self._device.write(self._BUFFER, end=2)
|
||||
return self._device.writeto_mem(self._address, address & 0xFF, [val & 0xFF])
|
||||
|
||||
def _write_u16(self, address, val):
|
||||
# Write a 16-bit BE unsigned value to the specified 8-bit address.
|
||||
# with self._device:
|
||||
# self._BUFFER[0] = address & 0xFF
|
||||
# self._BUFFER[1] = (val >> 8) & 0xFF
|
||||
# self._BUFFER[2] = val & 0xFF
|
||||
# self._device.write(self._BUFFER)
|
||||
#self._device.write(self._BUFFER)
|
||||
return self._device.writeto_mem(self._address, address & 0xFF, [(val >> 8) & 0xFF, val & 0xFF])
|
||||
|
||||
def _get_spad_info(self):
|
||||
# Get reference SPAD count and type, returned as a 2-tuple of
|
||||
# count and boolean is_aperture. Based on code from:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
|
||||
for pair in ((0x80, 0x01), (0xFF, 0x01), (0x00, 0x00), (0xFF, 0x06)):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
self._write_u8(0x83, self._read_u8(0x83) | 0x04)
|
||||
for pair in (
|
||||
(0xFF, 0x07),
|
||||
(0x81, 0x01),
|
||||
(0x80, 0x01),
|
||||
(0x94, 0x6B),
|
||||
(0x83, 0x00),
|
||||
):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
start = time.monotonic()
|
||||
while self._read_u8(0x83) == 0x00:
|
||||
if (
|
||||
self.io_timeout_s > 0
|
||||
and (time.monotonic() - start) >= self.io_timeout_s
|
||||
):
|
||||
raise RuntimeError("Timeout waiting for VL53L0X!")
|
||||
self._write_u8(0x83, 0x01)
|
||||
tmp = self._read_u8(0x92)
|
||||
count = tmp & 0x7F
|
||||
is_aperture = ((tmp >> 7) & 0x01) == 1
|
||||
for pair in ((0x81, 0x00), (0xFF, 0x06)):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
self._write_u8(0x83, self._read_u8(0x83) & ~0x04)
|
||||
for pair in ((0xFF, 0x01), (0x00, 0x01), (0xFF, 0x00), (0x80, 0x00)):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
return (count, is_aperture)
|
||||
|
||||
def _perform_single_ref_calibration(self, vhv_init_byte):
|
||||
# based on VL53L0X_perform_single_ref_calibration() from ST API.
|
||||
self._write_u8(_SYSRANGE_START, 0x01 | vhv_init_byte & 0xFF)
|
||||
start = time.monotonic()
|
||||
while (self._read_u8(_RESULT_INTERRUPT_STATUS) & 0x07) == 0:
|
||||
if (
|
||||
self.io_timeout_s > 0
|
||||
and (time.monotonic() - start) >= self.io_timeout_s
|
||||
):
|
||||
raise RuntimeError("Timeout waiting for VL53L0X!")
|
||||
self._write_u8(_SYSTEM_INTERRUPT_CLEAR, 0x01)
|
||||
self._write_u8(_SYSRANGE_START, 0x00)
|
||||
|
||||
def _get_vcsel_pulse_period(self, vcsel_period_type):
|
||||
# pylint: disable=no-else-return
|
||||
# Disable should be removed when refactor can be tested
|
||||
if vcsel_period_type == _VCSEL_PERIOD_PRE_RANGE:
|
||||
val = self._read_u8(_PRE_RANGE_CONFIG_VCSEL_PERIOD)
|
||||
return (((val) + 1) & 0xFF) << 1
|
||||
elif vcsel_period_type == _VCSEL_PERIOD_FINAL_RANGE:
|
||||
val = self._read_u8(_FINAL_RANGE_CONFIG_VCSEL_PERIOD)
|
||||
return (((val) + 1) & 0xFF) << 1
|
||||
return 255
|
||||
|
||||
def _get_sequence_step_enables(self):
|
||||
# based on VL53L0X_GetSequenceStepEnables() from ST API
|
||||
sequence_config = self._read_u8(_SYSTEM_SEQUENCE_CONFIG)
|
||||
tcc = (sequence_config >> 4) & 0x1 > 0
|
||||
dss = (sequence_config >> 3) & 0x1 > 0
|
||||
msrc = (sequence_config >> 2) & 0x1 > 0
|
||||
pre_range = (sequence_config >> 6) & 0x1 > 0
|
||||
final_range = (sequence_config >> 7) & 0x1 > 0
|
||||
return (tcc, dss, msrc, pre_range, final_range)
|
||||
|
||||
def _get_sequence_step_timeouts(self, pre_range):
|
||||
# based on get_sequence_step_timeout() from ST API but modified by
|
||||
# pololu here:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
|
||||
pre_range_vcsel_period_pclks = self._get_vcsel_pulse_period(
|
||||
_VCSEL_PERIOD_PRE_RANGE
|
||||
)
|
||||
msrc_dss_tcc_mclks = (self._read_u8(_MSRC_CONFIG_TIMEOUT_MACROP) + 1) & 0xFF
|
||||
msrc_dss_tcc_us = _timeout_mclks_to_microseconds(
|
||||
msrc_dss_tcc_mclks, pre_range_vcsel_period_pclks
|
||||
)
|
||||
pre_range_mclks = _decode_timeout(
|
||||
self._read_u16(_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI)
|
||||
)
|
||||
pre_range_us = _timeout_mclks_to_microseconds(
|
||||
pre_range_mclks, pre_range_vcsel_period_pclks
|
||||
)
|
||||
final_range_vcsel_period_pclks = self._get_vcsel_pulse_period(
|
||||
_VCSEL_PERIOD_FINAL_RANGE
|
||||
)
|
||||
final_range_mclks = _decode_timeout(
|
||||
self._read_u16(_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI)
|
||||
)
|
||||
if pre_range:
|
||||
final_range_mclks -= pre_range_mclks
|
||||
final_range_us = _timeout_mclks_to_microseconds(
|
||||
final_range_mclks, final_range_vcsel_period_pclks
|
||||
)
|
||||
return (
|
||||
msrc_dss_tcc_us,
|
||||
pre_range_us,
|
||||
final_range_us,
|
||||
final_range_vcsel_period_pclks,
|
||||
pre_range_mclks,
|
||||
)
|
||||
|
||||
@property
|
||||
def signal_rate_limit(self):
|
||||
"""The signal rate limit in mega counts per second."""
|
||||
val = self._read_u16(_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT)
|
||||
# Return value converted from 16-bit 9.7 fixed point to float.
|
||||
return val / (1 << 7)
|
||||
|
||||
@signal_rate_limit.setter
|
||||
def signal_rate_limit(self, val):
|
||||
assert 0.0 <= val <= 511.99
|
||||
# Convert to 16-bit 9.7 fixed point value from a float.
|
||||
val = int(val * (1 << 7))
|
||||
self._write_u16(_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, val)
|
||||
|
||||
@property
|
||||
def measurement_timing_budget(self):
|
||||
"""The measurement timing budget in microseconds."""
|
||||
budget_us = 1910 + 960 # Start overhead + end overhead.
|
||||
tcc, dss, msrc, pre_range, final_range = self._get_sequence_step_enables()
|
||||
step_timeouts = self._get_sequence_step_timeouts(pre_range)
|
||||
msrc_dss_tcc_us, pre_range_us, final_range_us, _, _ = step_timeouts
|
||||
if tcc:
|
||||
budget_us += msrc_dss_tcc_us + 590
|
||||
if dss:
|
||||
budget_us += 2 * (msrc_dss_tcc_us + 690)
|
||||
elif msrc:
|
||||
budget_us += msrc_dss_tcc_us + 660
|
||||
if pre_range:
|
||||
budget_us += pre_range_us + 660
|
||||
if final_range:
|
||||
budget_us += final_range_us + 550
|
||||
self._measurement_timing_budget_us = budget_us
|
||||
return budget_us
|
||||
|
||||
@measurement_timing_budget.setter
|
||||
def measurement_timing_budget(self, budget_us):
|
||||
# pylint: disable=too-many-locals
|
||||
assert budget_us >= 20000
|
||||
used_budget_us = 1320 + 960 # Start (diff from get) + end overhead
|
||||
tcc, dss, msrc, pre_range, final_range = self._get_sequence_step_enables()
|
||||
step_timeouts = self._get_sequence_step_timeouts(pre_range)
|
||||
msrc_dss_tcc_us, pre_range_us, _ = step_timeouts[:3]
|
||||
final_range_vcsel_period_pclks, pre_range_mclks = step_timeouts[3:]
|
||||
if tcc:
|
||||
used_budget_us += msrc_dss_tcc_us + 590
|
||||
if dss:
|
||||
used_budget_us += 2 * (msrc_dss_tcc_us + 690)
|
||||
elif msrc:
|
||||
used_budget_us += msrc_dss_tcc_us + 660
|
||||
if pre_range:
|
||||
used_budget_us += pre_range_us + 660
|
||||
if final_range:
|
||||
used_budget_us += 550
|
||||
# "Note that the final range timeout is determined by the timing
|
||||
# budget and the sum of all other timeouts within the sequence.
|
||||
# If there is no room for the final range timeout, then an error
|
||||
# will be set. Otherwise the remaining time will be applied to
|
||||
# the final range."
|
||||
if used_budget_us > budget_us:
|
||||
raise ValueError("Requested timeout too big.")
|
||||
final_range_timeout_us = budget_us - used_budget_us
|
||||
final_range_timeout_mclks = _timeout_microseconds_to_mclks(
|
||||
final_range_timeout_us, final_range_vcsel_period_pclks
|
||||
)
|
||||
if pre_range:
|
||||
final_range_timeout_mclks += pre_range_mclks
|
||||
self._write_u16(
|
||||
_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI,
|
||||
_encode_timeout(final_range_timeout_mclks),
|
||||
)
|
||||
self._measurement_timing_budget_us = budget_us
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
"""Perform a single reading of the range for an object in front of
|
||||
the sensor and return the distance in millimeters.
|
||||
"""
|
||||
# Adapted from readRangeSingleMillimeters &
|
||||
# readRangeContinuousMillimeters in pololu code at:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
|
||||
for pair in (
|
||||
(0x80, 0x01),
|
||||
(0xFF, 0x01),
|
||||
(0x00, 0x00),
|
||||
(0x91, self._stop_variable),
|
||||
(0x00, 0x01),
|
||||
(0xFF, 0x00),
|
||||
(0x80, 0x00),
|
||||
(_SYSRANGE_START, 0x01),
|
||||
):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
start = time.monotonic()
|
||||
while (self._read_u8(_SYSRANGE_START) & 0x01) > 0:
|
||||
if (
|
||||
self.io_timeout_s > 0
|
||||
and (time.monotonic() - start) >= self.io_timeout_s
|
||||
):
|
||||
raise RuntimeError("Timeout waiting for VL53L0X!")
|
||||
start = time.monotonic()
|
||||
while (self._read_u8(_RESULT_INTERRUPT_STATUS) & 0x07) == 0:
|
||||
if (
|
||||
self.io_timeout_s > 0
|
||||
and (time.monotonic() - start) >= self.io_timeout_s
|
||||
):
|
||||
raise RuntimeError("Timeout waiting for VL53L0X!")
|
||||
# assumptions: Linearity Corrective Gain is 1000 (default)
|
||||
# fractional ranging is not enabled
|
||||
range_mm = self._read_u16(_RESULT_RANGE_STATUS + 10)
|
||||
self._write_u8(_SYSTEM_INTERRUPT_CLEAR, 0x01)
|
||||
return range_mm
|
||||
|
||||
# def set_address(self, new_address):
|
||||
# """Set a new I2C address to the instantaited object. This is only called when using
|
||||
# multiple VL53L0X sensors on the same I2C bus (SDA & SCL pins). See also the
|
||||
# `example <examples.html#multiple-vl53l0x-on-same-i2c-bus>`_ for proper usage.
|
||||
#
|
||||
# :param int new_address: The 7-bit `int` that is to be assigned to the VL53L0X sensor.
|
||||
# The address that is assigned should NOT be already in use by another device on the
|
||||
# I2C bus.
|
||||
#
|
||||
# .. important:: To properly set the address to an individual VL53L0X sensor, you must
|
||||
# first ensure that all other VL53L0X sensors (using the default address of ``0x29``)
|
||||
# on the same I2C bus are in their off state by pulling the "SHDN" pins LOW. When the
|
||||
# "SHDN" pin is pulled HIGH again the default I2C address is ``0x29``.
|
||||
# """
|
||||
# self._write_u8(_I2C_SLAVE_DEVICE_ADDRESS, new_address & 0x7F)
|
||||
# self._device = i2c_device.I2CDevice(self._i2c, new_address)
|
||||
|
||||
def start_measure(self):
|
||||
"""Perform a single reading of the range for an object in front of
|
||||
the sensor and return the distance in millimeters.
|
||||
"""
|
||||
# Adapted from readRangeSingleMillimeters &
|
||||
# readRangeContinuousMillimeters in pololu code at:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/VL53L0X.cpp
|
||||
for pair in (
|
||||
(0x80, 0x01),
|
||||
(0xFF, 0x01),
|
||||
(0x00, 0x00),
|
||||
(0x91, self._stop_variable),
|
||||
(0x00, 0x01),
|
||||
(0xFF, 0x00),
|
||||
(0x80, 0x00),
|
||||
(_SYSRANGE_START, 0x01),
|
||||
):
|
||||
self._write_u8(pair[0], pair[1])
|
||||
start = time.monotonic()
|
||||
while (self._read_u8(_SYSRANGE_START) & 0x01) > 0:
|
||||
if (
|
||||
self.io_timeout_s > 0
|
||||
and (time.monotonic() - start) >= self.io_timeout_s
|
||||
):
|
||||
raise RuntimeError("Timeout waiting for VL53L0X!")
|
||||
|
||||
def read_measure(self):
|
||||
# assumptions: Linearity Corrective Gain is 1000 (default)
|
||||
# fractional ranging is not enabled
|
||||
range_mm = self._read_u16(_RESULT_RANGE_STATUS + 10)
|
||||
self._write_u8(_SYSTEM_INTERRUPT_CLEAR, 0x01)
|
||||
return range_mm
|
||||
452
examples/external/bmp280.py
vendored
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
# From https://github.com/adafruit/Adafruit_CircuitPython_BMP280 which is originally licensed : see below.
|
||||
# Minor changes to work on micropython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# SPDX-FileCopyrightText: 2017 ladyada for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
`adafruit_bmp280` - Adafruit BMP280 - Temperature & Barometic Pressure Sensor
|
||||
===============================================================================
|
||||
|
||||
CircuitPython driver from BMP280 Temperature and Barometic Pressure sensor
|
||||
|
||||
* Author(s): ladyada
|
||||
"""
|
||||
|
||||
import math
|
||||
from time import sleep
|
||||
|
||||
try:
|
||||
import struct
|
||||
except ImportError:
|
||||
import ustruct as struct
|
||||
from micropython import const
|
||||
|
||||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BMP280.git"
|
||||
|
||||
# I2C ADDRESS/BITS/SETTINGS
|
||||
# -----------------------------------------------------------------------
|
||||
_CHIP_ID = const(0x58)
|
||||
|
||||
_REGISTER_CHIPID = const(0xD0)
|
||||
_REGISTER_DIG_T1 = const(0x88)
|
||||
_REGISTER_SOFTRESET = const(0xE0)
|
||||
_REGISTER_STATUS = const(0xF3)
|
||||
_REGISTER_CTRL_MEAS = const(0xF4)
|
||||
_REGISTER_CONFIG = const(0xF5)
|
||||
_REGISTER_PRESSUREDATA = const(0xF7)
|
||||
_REGISTER_TEMPDATA = const(0xFA)
|
||||
|
||||
_BMP280_PRESSURE_MIN_HPA = const(300)
|
||||
_BMP280_PRESSURE_MAX_HPA = const(1100)
|
||||
|
||||
|
||||
"""iir_filter values"""
|
||||
IIR_FILTER_DISABLE = const(0)
|
||||
IIR_FILTER_X2 = const(0x01)
|
||||
IIR_FILTER_X4 = const(0x02)
|
||||
IIR_FILTER_X8 = const(0x03)
|
||||
IIR_FILTER_X16 = const(0x04)
|
||||
|
||||
_BMP280_IIR_FILTERS = (
|
||||
IIR_FILTER_DISABLE,
|
||||
IIR_FILTER_X2,
|
||||
IIR_FILTER_X4,
|
||||
IIR_FILTER_X8,
|
||||
IIR_FILTER_X16,
|
||||
)
|
||||
|
||||
"""overscan values for temperature, pressure, and humidity"""
|
||||
OVERSCAN_DISABLE = const(0x00)
|
||||
OVERSCAN_X1 = const(0x01)
|
||||
OVERSCAN_X2 = const(0x02)
|
||||
OVERSCAN_X4 = const(0x03)
|
||||
OVERSCAN_X8 = const(0x04)
|
||||
OVERSCAN_X16 = const(0x05)
|
||||
|
||||
_BMP280_OVERSCANS = {
|
||||
OVERSCAN_DISABLE: 0,
|
||||
OVERSCAN_X1: 1,
|
||||
OVERSCAN_X2: 2,
|
||||
OVERSCAN_X4: 4,
|
||||
OVERSCAN_X8: 8,
|
||||
OVERSCAN_X16: 16,
|
||||
}
|
||||
|
||||
"""mode values"""
|
||||
MODE_SLEEP = const(0x00)
|
||||
MODE_FORCE = const(0x01)
|
||||
MODE_NORMAL = const(0x03)
|
||||
|
||||
_BMP280_MODES = (MODE_SLEEP, MODE_FORCE, MODE_NORMAL)
|
||||
"""
|
||||
standby timeconstant values
|
||||
TC_X[_Y] where X=milliseconds and Y=tenths of a millisecond
|
||||
"""
|
||||
STANDBY_TC_0_5 = const(0x00) # 0.5ms
|
||||
STANDBY_TC_10 = const(0x06) # 10ms
|
||||
STANDBY_TC_20 = const(0x07) # 20ms
|
||||
STANDBY_TC_62_5 = const(0x01) # 62.5ms
|
||||
STANDBY_TC_125 = const(0x02) # 125ms
|
||||
STANDBY_TC_250 = const(0x03) # 250ms
|
||||
STANDBY_TC_500 = const(0x04) # 500ms
|
||||
STANDBY_TC_1000 = const(0x05) # 1000ms
|
||||
|
||||
_BMP280_STANDBY_TCS = (
|
||||
STANDBY_TC_0_5,
|
||||
STANDBY_TC_10,
|
||||
STANDBY_TC_20,
|
||||
STANDBY_TC_62_5,
|
||||
STANDBY_TC_125,
|
||||
STANDBY_TC_250,
|
||||
STANDBY_TC_500,
|
||||
STANDBY_TC_1000,
|
||||
)
|
||||
|
||||
|
||||
class Adafruit_BMP280: # pylint: disable=invalid-name
|
||||
"""Base BMP280 object. Use `Adafruit_BMP280_I2C` or `Adafruit_BMP280_SPI` instead of this. This
|
||||
checks the BMP280 was found, reads the coefficients and enables the sensor for continuous
|
||||
reads"""
|
||||
|
||||
def __init__(self):
|
||||
# Check device ID.
|
||||
chip_id = self._read_byte(_REGISTER_CHIPID)
|
||||
if _CHIP_ID != chip_id:
|
||||
raise RuntimeError("Failed to find BMP280! Chip ID 0x%x" % chip_id)
|
||||
# Set some reasonable defaults.
|
||||
self._iir_filter = IIR_FILTER_DISABLE
|
||||
self._overscan_temperature = OVERSCAN_X2
|
||||
self._overscan_pressure = OVERSCAN_X16
|
||||
self._t_standby = STANDBY_TC_0_5
|
||||
self._mode = MODE_SLEEP
|
||||
self._reset()
|
||||
self._read_coefficients()
|
||||
self._write_ctrl_meas()
|
||||
self._write_config()
|
||||
self.sea_level_pressure = 1013.25
|
||||
"""Pressure in hectoPascals at sea level. Used to calibrate `altitude`."""
|
||||
self._t_fine = None
|
||||
|
||||
def _read_temperature(self):
|
||||
# perform one measurement
|
||||
if self.mode != MODE_NORMAL:
|
||||
self.mode = MODE_FORCE
|
||||
# Wait for conversion to complete
|
||||
while self._get_status() & 0x08:
|
||||
sleep(0.002)
|
||||
raw_temperature = (
|
||||
self._read24(_REGISTER_TEMPDATA) / 16
|
||||
) # lowest 4 bits get dropped
|
||||
# print("raw temp: ", UT)
|
||||
var1 = (
|
||||
raw_temperature / 16384.0 - self._temp_calib[0] / 1024.0
|
||||
) * self._temp_calib[1]
|
||||
# print(var1)
|
||||
var2 = (
|
||||
(raw_temperature / 131072.0 - self._temp_calib[0] / 8192.0)
|
||||
* (raw_temperature / 131072.0 - self._temp_calib[0] / 8192.0)
|
||||
) * self._temp_calib[2]
|
||||
# print(var2)
|
||||
|
||||
self._t_fine = int(var1 + var2)
|
||||
# print("t_fine: ", self.t_fine)
|
||||
|
||||
def _reset(self):
|
||||
"""Soft reset the sensor"""
|
||||
self._write_register_byte(_REGISTER_SOFTRESET, 0xB6)
|
||||
sleep(0.004) # Datasheet says 2ms. Using 4ms just to be safe
|
||||
|
||||
def _write_ctrl_meas(self):
|
||||
"""
|
||||
Write the values to the ctrl_meas register in the device
|
||||
ctrl_meas sets the pressure and temperature data acquistion options
|
||||
"""
|
||||
self._write_register_byte(_REGISTER_CTRL_MEAS, self._ctrl_meas)
|
||||
|
||||
def _get_status(self):
|
||||
"""Get the value from the status register in the device """
|
||||
return self._read_byte(_REGISTER_STATUS)
|
||||
|
||||
def _read_config(self):
|
||||
"""Read the value from the config register in the device """
|
||||
return self._read_byte(_REGISTER_CONFIG)
|
||||
|
||||
def _write_config(self):
|
||||
"""Write the value to the config register in the device """
|
||||
normal_flag = False
|
||||
if self._mode == MODE_NORMAL:
|
||||
# Writes to the config register may be ignored while in Normal mode
|
||||
normal_flag = True
|
||||
self.mode = MODE_SLEEP # So we switch to Sleep mode first
|
||||
self._write_register_byte(_REGISTER_CONFIG, self._config)
|
||||
if normal_flag:
|
||||
self.mode = MODE_NORMAL
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
"""
|
||||
Operation mode
|
||||
Allowed values are set in the MODE enum class
|
||||
"""
|
||||
return self._mode
|
||||
|
||||
@mode.setter
|
||||
def mode(self, value):
|
||||
if not value in _BMP280_MODES:
|
||||
raise ValueError("Mode '%s' not supported" % (value))
|
||||
self._mode = value
|
||||
self._write_ctrl_meas()
|
||||
|
||||
@property
|
||||
def standby_period(self):
|
||||
"""
|
||||
Control the inactive period when in Normal mode
|
||||
Allowed standby periods are set the STANDBY enum class
|
||||
"""
|
||||
return self._t_standby
|
||||
|
||||
@standby_period.setter
|
||||
def standby_period(self, value):
|
||||
if not value in _BMP280_STANDBY_TCS:
|
||||
raise ValueError("Standby Period '%s' not supported" % (value))
|
||||
if self._t_standby == value:
|
||||
return
|
||||
self._t_standby = value
|
||||
self._write_config()
|
||||
|
||||
@property
|
||||
def overscan_temperature(self):
|
||||
"""
|
||||
Temperature Oversampling
|
||||
Allowed values are set in the OVERSCAN enum class
|
||||
"""
|
||||
return self._overscan_temperature
|
||||
|
||||
@overscan_temperature.setter
|
||||
def overscan_temperature(self, value):
|
||||
if not value in _BMP280_OVERSCANS:
|
||||
raise ValueError("Overscan value '%s' not supported" % (value))
|
||||
self._overscan_temperature = value
|
||||
self._write_ctrl_meas()
|
||||
|
||||
@property
|
||||
def overscan_pressure(self):
|
||||
"""
|
||||
Pressure Oversampling
|
||||
Allowed values are set in the OVERSCAN enum class
|
||||
"""
|
||||
return self._overscan_pressure
|
||||
|
||||
@overscan_pressure.setter
|
||||
def overscan_pressure(self, value):
|
||||
if not value in _BMP280_OVERSCANS:
|
||||
raise ValueError("Overscan value '%s' not supported" % (value))
|
||||
self._overscan_pressure = value
|
||||
self._write_ctrl_meas()
|
||||
|
||||
@property
|
||||
def iir_filter(self):
|
||||
"""
|
||||
Controls the time constant of the IIR filter
|
||||
Allowed values are set in the IIR_FILTER enum class
|
||||
"""
|
||||
return self._iir_filter
|
||||
|
||||
@iir_filter.setter
|
||||
def iir_filter(self, value):
|
||||
if not value in _BMP280_IIR_FILTERS:
|
||||
raise ValueError("IIR Filter '%s' not supported" % (value))
|
||||
self._iir_filter = value
|
||||
self._write_config()
|
||||
|
||||
@property
|
||||
def _config(self):
|
||||
"""Value to be written to the device's config register """
|
||||
config = 0
|
||||
if self.mode == MODE_NORMAL:
|
||||
config += self._t_standby << 5
|
||||
if self._iir_filter:
|
||||
config += self._iir_filter << 2
|
||||
return config
|
||||
|
||||
@property
|
||||
def _ctrl_meas(self):
|
||||
"""Value to be written to the device's ctrl_meas register """
|
||||
ctrl_meas = self.overscan_temperature << 5
|
||||
ctrl_meas += self.overscan_pressure << 2
|
||||
ctrl_meas += self.mode
|
||||
return ctrl_meas
|
||||
|
||||
@property
|
||||
def measurement_time_typical(self):
|
||||
"""Typical time in milliseconds required to complete a measurement in normal mode"""
|
||||
meas_time_ms = 1
|
||||
if self.overscan_temperature != OVERSCAN_DISABLE:
|
||||
meas_time_ms += 2 * _BMP280_OVERSCANS.get(self.overscan_temperature)
|
||||
if self.overscan_pressure != OVERSCAN_DISABLE:
|
||||
meas_time_ms += 2 * _BMP280_OVERSCANS.get(self.overscan_pressure) + 0.5
|
||||
return meas_time_ms
|
||||
|
||||
@property
|
||||
def measurement_time_max(self):
|
||||
"""Maximum time in milliseconds required to complete a measurement in normal mode"""
|
||||
meas_time_ms = 1.25
|
||||
if self.overscan_temperature != OVERSCAN_DISABLE:
|
||||
meas_time_ms += 2.3 * _BMP280_OVERSCANS.get(self.overscan_temperature)
|
||||
if self.overscan_pressure != OVERSCAN_DISABLE:
|
||||
meas_time_ms += 2.3 * _BMP280_OVERSCANS.get(self.overscan_pressure) + 0.575
|
||||
return meas_time_ms
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""The compensated temperature in degrees celsius."""
|
||||
self._read_temperature()
|
||||
return self._t_fine / 5120.0
|
||||
|
||||
@property
|
||||
def pressure(self):
|
||||
"""
|
||||
The compensated pressure in hectoPascals.
|
||||
returns None if pressure measurement is disabled
|
||||
"""
|
||||
self._read_temperature()
|
||||
|
||||
# Algorithm from the BMP280 driver
|
||||
# https://github.com/BoschSensortec/BMP280_driver/blob/master/bmp280.c
|
||||
adc = self._read24(_REGISTER_PRESSUREDATA) / 16 # lowest 4 bits get dropped
|
||||
var1 = float(self._t_fine) / 2.0 - 64000.0
|
||||
var2 = var1 * var1 * self._pressure_calib[5] / 32768.0
|
||||
var2 = var2 + var1 * self._pressure_calib[4] * 2.0
|
||||
var2 = var2 / 4.0 + self._pressure_calib[3] * 65536.0
|
||||
var3 = self._pressure_calib[2] * var1 * var1 / 524288.0
|
||||
var1 = (var3 + self._pressure_calib[1] * var1) / 524288.0
|
||||
var1 = (1.0 + var1 / 32768.0) * self._pressure_calib[0]
|
||||
if not var1:
|
||||
return _BMP280_PRESSURE_MIN_HPA
|
||||
pressure = 1048576.0 - adc
|
||||
pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1
|
||||
var1 = self._pressure_calib[8] * pressure * pressure / 2147483648.0
|
||||
var2 = pressure * self._pressure_calib[7] / 32768.0
|
||||
pressure = pressure + (var1 + var2 + self._pressure_calib[6]) / 16.0
|
||||
pressure /= 100
|
||||
if pressure < _BMP280_PRESSURE_MIN_HPA:
|
||||
return _BMP280_PRESSURE_MIN_HPA
|
||||
if pressure > _BMP280_PRESSURE_MAX_HPA:
|
||||
return _BMP280_PRESSURE_MAX_HPA
|
||||
return pressure
|
||||
|
||||
@property
|
||||
def altitude(self):
|
||||
"""The altitude based on the sea level pressure (`sea_level_pressure`) - which you must
|
||||
enter ahead of time)"""
|
||||
p = self.pressure # in Si units for hPascal
|
||||
return 44330 * (1.0 - math.pow(p / self.sea_level_pressure, 0.1903))
|
||||
|
||||
####################### Internal helpers ################################
|
||||
def _read_coefficients(self):
|
||||
"""Read & save the calibration coefficients"""
|
||||
coeff = self._read_register(_REGISTER_DIG_T1, 24)
|
||||
coeff = list(struct.unpack("<HhhHhhhhhhhh", bytes(coeff)))
|
||||
coeff = [float(i) for i in coeff]
|
||||
# The temp_calib lines up with DIG_T# registers.
|
||||
self._temp_calib = coeff[:3]
|
||||
self._pressure_calib = coeff[3:]
|
||||
# print("%d %d %d" % (self._temp_calib[0], self._temp_calib[1], self._temp_calib[2]))
|
||||
# print("%d %d %d" % (self._pressure_calib[0], self._pressure_calib[1],
|
||||
# self._pressure_calib[2]))
|
||||
# print("%d %d %d" % (self._pressure_calib[3], self._pressure_calib[4],
|
||||
# self._pressure_calib[5]))
|
||||
# print("%d %d %d" % (self._pressure_calib[6], self._pressure_calib[7],
|
||||
# self._pressure_calib[8]))
|
||||
|
||||
def _read_byte(self, register):
|
||||
"""Read a byte register value and return it"""
|
||||
return self._read_register(register, 1)[0]
|
||||
|
||||
def _read24(self, register):
|
||||
"""Read an unsigned 24-bit value as a floating point and return it."""
|
||||
ret = 0.0
|
||||
for b in self._read_register(register, 3):
|
||||
ret *= 256.0
|
||||
ret += float(b & 0xFF)
|
||||
return ret
|
||||
|
||||
def _read_register(self, register, length):
|
||||
"""Low level register reading, not implemented in base class"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def _write_register_byte(self, register, value):
|
||||
"""Low level register writing, not implemented in base class"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class Adafruit_BMP280_I2C(Adafruit_BMP280): # pylint: disable=invalid-name
|
||||
"""Driver for I2C connected BMP280. Default address is 0x77 but another address can be passed
|
||||
in as an argument"""
|
||||
|
||||
def __init__(self, i2c, address=0x77):
|
||||
#import adafruit_bus_device.i2c_device as i2c_device # pylint: disable=import-outside-toplevel
|
||||
|
||||
#self._i2c = i2c_device.I2CDevice(i2c, address)
|
||||
self.address = address
|
||||
self.i2c = i2c
|
||||
super().__init__()
|
||||
|
||||
def _read_register(self, register, length):
|
||||
"""Low level register reading over I2C, returns a list of values"""
|
||||
# with self._i2c as i2c:
|
||||
# i2c.write(bytes([register & 0xFF]))
|
||||
# result = bytearray(length)
|
||||
# i2c.readinto(result)
|
||||
# # print("$%02X => %s" % (register, [hex(i) for i in result]))
|
||||
# return result
|
||||
return self.i2c.readfrom_mem(self.address, register & 0xFF, length)
|
||||
|
||||
def _write_register_byte(self, register, value):
|
||||
"""Low level register writing over I2C, writes one 8-bit value"""
|
||||
# with self._i2c as i2c:
|
||||
# i2c.write(bytes([register & 0xFF, value & 0xFF]))
|
||||
# # print("$%02X <= 0x%02X" % (register, value))
|
||||
return self.i2c.writeto_mem(self.address, register & 0xFF, [value & 0xFF])
|
||||
|
||||
class Adafruit_BMP280_SPI(Adafruit_BMP280):
|
||||
"""Driver for SPI connected BMP280. Default clock rate is 100000 but can be changed with
|
||||
'baudrate'"""
|
||||
|
||||
def __init__(self, spi, cs, baudrate=100000):
|
||||
#import adafruit_bus_device.spi_device as spi_device # pylint: disable=import-outside-toplevel
|
||||
|
||||
self._spi = spi
|
||||
self.cs_pin = cs
|
||||
super().__init__()
|
||||
|
||||
def _read_register(self, register, length):
|
||||
"""Low level register reading over SPI, returns a list of values"""
|
||||
register = (register | 0x80) & 0xFF # Read single, bit 7 high.
|
||||
# with self._spi as spi:
|
||||
# # pylint: disable=no-member
|
||||
# spi.write(bytearray([register]))
|
||||
# result = bytearray(length)
|
||||
# spi.readinto(result)
|
||||
# # print("$%02X => %s" % (register, [hex(i) for i in result]))
|
||||
# return result
|
||||
self.cs_pin.value(0)
|
||||
self._spi.write(bytearray([register]))
|
||||
#self.cs_pin.value(1)
|
||||
result = bytearray(length)
|
||||
#self.cs_pin.value(0)
|
||||
self._spi.readinto(result)
|
||||
self.cs_pin.value(1)
|
||||
return result
|
||||
|
||||
def _write_register_byte(self, register, value):
|
||||
"""Low level register writing over SPI, writes one 8-bit value"""
|
||||
register &= 0x7F # Write, bit 7 low.
|
||||
#with self._spi as spi:
|
||||
# # pylint: disable=no-member
|
||||
# spi.write(bytes([register, value & 0xFF]))
|
||||
self._spi.write(bytes([register, value & 0xFF]))
|
||||
430
examples/external/gc9a01.py
vendored
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
# Round lcd driver GC9A01 (240x240). Driver derived from Waveshare team which which is originally licensed : see below
|
||||
# Minor changes to work on micropython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# /*****************************************************************************
|
||||
# * | File : epdconfig.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Hardware underlying interface
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V1.0
|
||||
# * | Date : 2019-06-21
|
||||
# * | Info :
|
||||
# ******************************************************************************
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documnetation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
|
||||
import time
|
||||
import numpy as np
|
||||
from machine import Pin, PWM
|
||||
|
||||
class BaseLcd:
|
||||
def __init__(self, spi, dc, rst, cs, bl, bl_freq=1000):
|
||||
#def __init__(self,spi=spidev.SpiDev(0,0),spi_freq=40000000,rst = 27,dc = 25,bl = 18,bl_freq=1000,i2c=None,i2c_freq=100000):
|
||||
# import RPi.GPIO
|
||||
self.np = np
|
||||
self.SPI = spi
|
||||
self.RST_PIN = rst
|
||||
self.DC_PIN = dc
|
||||
self.BL_PIN = bl
|
||||
self.CS_PIN = cs
|
||||
#self.SPEED =spi_freq
|
||||
self.BL_freq=bl_freq
|
||||
#self.GPIO = RPi.GPIO
|
||||
#self.GPIO.cleanup()
|
||||
# self.GPIO.setmode(self.GPIO.BCM)
|
||||
# self.GPIO.setwarnings(False)
|
||||
# self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
||||
# self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
||||
# self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
|
||||
# self.GPIO.output(self.BL_PIN, self.GPIO.HIGH)
|
||||
self.RST_PIN.init(Pin.OUT)
|
||||
self.DC_PIN.init(Pin.OUT)
|
||||
self.BL_PIN.init(Pin.OUT, Pin.HIGH)
|
||||
self.CS_PIN.init(Pin.OUT, Pin.HIGH)
|
||||
#Initialize SPI
|
||||
self.SPI = spi
|
||||
# if self.SPI!=None :
|
||||
# self.SPI.max_speed_hz = spi_freq
|
||||
# self.SPI.mode = 0b00
|
||||
self._pwm = PWM(self.BL_PIN)
|
||||
self._pwm.freq(self.BL_freq)
|
||||
self._pwm.duty_u16(32000)
|
||||
|
||||
def digital_write(self, pin, value):
|
||||
#self.GPIO.output(pin, value)
|
||||
pin.value(value)
|
||||
|
||||
def digital_read(self, pin):
|
||||
#return self.GPIO.input(pin)
|
||||
return pin.value()
|
||||
|
||||
def delay_ms(self, delaytime):
|
||||
time.sleep(delaytime / 1000.0)
|
||||
|
||||
def spi_writebyte(self, data):
|
||||
if self.SPI!=None :
|
||||
#self.SPI.writebytes(data)
|
||||
self.SPI.write(data)
|
||||
|
||||
def bl_DutyCycle(self, duty):
|
||||
#self._pwm.ChangeDutyCycle(duty)
|
||||
self._pwm.duty_u16(duty)
|
||||
|
||||
def bl_Frequency(self,freq):
|
||||
#self._pwm.ChangeFrequency(freq)
|
||||
self._pwm.freq(freq)
|
||||
|
||||
def module_init(self):
|
||||
# self.RST_PIN.setup(self.DC_PIN, self.GPIO.OUT)
|
||||
# self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
||||
# self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
|
||||
self.RST_PIN.init(Pin.OUT)
|
||||
self.DC_PIN.init(Pin.OUT)
|
||||
#self.BL_PIN.init(Pin.OUT)
|
||||
# self._pwm=self.GPIO.PWM(self.BL_PIN,self.BL_freq)
|
||||
# self._pwm.start(100)
|
||||
# if self.SPI!=None :
|
||||
# self.SPI.max_speed_hz = self.SPEED
|
||||
# self.SPI.mode = 0b00
|
||||
return 0
|
||||
|
||||
|
||||
class Lcd(BaseLcd):
|
||||
|
||||
width = 240
|
||||
height = 240
|
||||
|
||||
def command(self, cmd):
|
||||
#self.digital_write(self.DC_PIN, self.GPIO.LOW)
|
||||
self.CS_PIN.value(Pin.LOW)
|
||||
self.DC_PIN.value(Pin.LOW)
|
||||
self.spi_writebyte([cmd])
|
||||
self.CS_PIN.value(Pin.HIGH)
|
||||
|
||||
def data(self, val):
|
||||
#self.digital_write(self.DC_PIN, self.GPIO.HIGH)
|
||||
self.CS_PIN.value(Pin.LOW)
|
||||
self.DC_PIN.value(Pin.HIGH)
|
||||
self.spi_writebyte([val])
|
||||
self.CS_PIN.value(Pin.HIGH)
|
||||
|
||||
def reset(self):
|
||||
"""Reset the display"""
|
||||
#self.GPIO.output(self.RST_PIN,self.GPIO.HIGH)
|
||||
self.RST_PIN.value(Pin.HIGH)
|
||||
time.sleep(0.01)
|
||||
#self.GPIO.output(self.RST_PIN,self.GPIO.LOW)
|
||||
self.RST_PIN.value(Pin.LOW)
|
||||
time.sleep(0.01)
|
||||
#self.GPIO.output(self.RST_PIN,self.GPIO.HIGH)
|
||||
self.RST_PIN.value(Pin.HIGH)
|
||||
time.sleep(0.01)
|
||||
|
||||
def Init(self):
|
||||
"""Initialize dispaly"""
|
||||
self.module_init()
|
||||
self.reset()
|
||||
|
||||
self.command(0xEF)
|
||||
self.command(0xEB)
|
||||
self.data(0x14)
|
||||
|
||||
self.command(0xFE)
|
||||
self.command(0xEF)
|
||||
|
||||
self.command(0xEB)
|
||||
self.data(0x14)
|
||||
|
||||
self.command(0x84)
|
||||
self.data(0x40)
|
||||
|
||||
self.command(0x85)
|
||||
self.data(0xFF)
|
||||
|
||||
self.command(0x86)
|
||||
self.data(0xFF)
|
||||
|
||||
self.command(0x87)
|
||||
self.data(0xFF)
|
||||
|
||||
self.command(0x88)
|
||||
self.data(0x0A)
|
||||
|
||||
self.command(0x89)
|
||||
self.data(0x21)
|
||||
|
||||
self.command(0x8A)
|
||||
self.data(0x00)
|
||||
|
||||
self.command(0x8B)
|
||||
self.data(0x80)
|
||||
|
||||
self.command(0x8C)
|
||||
self.data(0x01)
|
||||
|
||||
self.command(0x8D)
|
||||
self.data(0x01)
|
||||
|
||||
self.command(0x8E)
|
||||
self.data(0xFF)
|
||||
|
||||
self.command(0x8F)
|
||||
self.data(0xFF)
|
||||
|
||||
|
||||
self.command(0xB6)
|
||||
self.data(0x00)
|
||||
self.data(0x20)
|
||||
|
||||
self.command(0x36)
|
||||
self.data(0x08)
|
||||
|
||||
self.command(0x3A)
|
||||
self.data(0x05)
|
||||
|
||||
|
||||
self.command(0x90)
|
||||
self.data(0x08)
|
||||
self.data(0x08)
|
||||
self.data(0x08)
|
||||
self.data(0x08)
|
||||
|
||||
self.command(0xBD)
|
||||
self.data(0x06)
|
||||
|
||||
self.command(0xBC)
|
||||
self.data(0x00)
|
||||
|
||||
self.command(0xFF)
|
||||
self.data(0x60)
|
||||
self.data(0x01)
|
||||
self.data(0x04)
|
||||
|
||||
self.command(0xC3)
|
||||
self.data(0x13)
|
||||
self.command(0xC4)
|
||||
self.data(0x13)
|
||||
|
||||
self.command(0xC9)
|
||||
self.data(0x22)
|
||||
|
||||
self.command(0xBE)
|
||||
self.data(0x11)
|
||||
|
||||
self.command(0xE1)
|
||||
self.data(0x10)
|
||||
self.data(0x0E)
|
||||
|
||||
self.command(0xDF)
|
||||
self.data(0x21)
|
||||
self.data(0x0c)
|
||||
self.data(0x02)
|
||||
|
||||
self.command(0xF0)
|
||||
self.data(0x45)
|
||||
self.data(0x09)
|
||||
self.data(0x08)
|
||||
self.data(0x08)
|
||||
self.data(0x26)
|
||||
self.data(0x2A)
|
||||
|
||||
self.command(0xF1)
|
||||
self.data(0x43)
|
||||
self.data(0x70)
|
||||
self.data(0x72)
|
||||
self.data(0x36)
|
||||
self.data(0x37)
|
||||
self.data(0x6F)
|
||||
|
||||
|
||||
self.command(0xF2)
|
||||
self.data(0x45)
|
||||
self.data(0x09)
|
||||
self.data(0x08)
|
||||
self.data(0x08)
|
||||
self.data(0x26)
|
||||
self.data(0x2A)
|
||||
|
||||
self.command(0xF3)
|
||||
self.data(0x43)
|
||||
self.data(0x70)
|
||||
self.data(0x72)
|
||||
self.data(0x36)
|
||||
self.data(0x37)
|
||||
self.data(0x6F)
|
||||
|
||||
self.command(0xED)
|
||||
self.data(0x1B)
|
||||
self.data(0x0B)
|
||||
|
||||
self.command(0xAE)
|
||||
self.data(0x77)
|
||||
|
||||
self.command(0xCD)
|
||||
self.data(0x63)
|
||||
|
||||
|
||||
self.command(0x70)
|
||||
self.data(0x07)
|
||||
self.data(0x07)
|
||||
self.data(0x04)
|
||||
self.data(0x0E)
|
||||
self.data(0x0F)
|
||||
self.data(0x09)
|
||||
self.data(0x07)
|
||||
self.data(0x08)
|
||||
self.data(0x03)
|
||||
|
||||
self.command(0xE8)
|
||||
self.data(0x34)
|
||||
|
||||
self.command(0x62)
|
||||
self.data(0x18)
|
||||
self.data(0x0D)
|
||||
self.data(0x71)
|
||||
self.data(0xED)
|
||||
self.data(0x70)
|
||||
self.data(0x70)
|
||||
self.data(0x18)
|
||||
self.data(0x0F)
|
||||
self.data(0x71)
|
||||
self.data(0xEF)
|
||||
self.data(0x70)
|
||||
self.data(0x70)
|
||||
|
||||
self.command(0x63)
|
||||
self.data(0x18)
|
||||
self.data(0x11)
|
||||
self.data(0x71)
|
||||
self.data(0xF1)
|
||||
self.data(0x70)
|
||||
self.data(0x70)
|
||||
self.data(0x18)
|
||||
self.data(0x13)
|
||||
self.data(0x71)
|
||||
self.data(0xF3)
|
||||
self.data(0x70)
|
||||
self.data(0x70)
|
||||
|
||||
self.command(0x64)
|
||||
self.data(0x28)
|
||||
self.data(0x29)
|
||||
self.data(0xF1)
|
||||
self.data(0x01)
|
||||
self.data(0xF1)
|
||||
self.data(0x00)
|
||||
self.data(0x07)
|
||||
|
||||
self.command(0x66)
|
||||
self.data(0x3C)
|
||||
self.data(0x00)
|
||||
self.data(0xCD)
|
||||
self.data(0x67)
|
||||
self.data(0x45)
|
||||
self.data(0x45)
|
||||
self.data(0x10)
|
||||
self.data(0x00)
|
||||
self.data(0x00)
|
||||
self.data(0x00)
|
||||
|
||||
self.command(0x67)
|
||||
self.data(0x00)
|
||||
self.data(0x3C)
|
||||
self.data(0x00)
|
||||
self.data(0x00)
|
||||
self.data(0x00)
|
||||
self.data(0x01)
|
||||
self.data(0x54)
|
||||
self.data(0x10)
|
||||
self.data(0x32)
|
||||
self.data(0x98)
|
||||
|
||||
self.command(0x74)
|
||||
self.data(0x10)
|
||||
self.data(0x85)
|
||||
self.data(0x80)
|
||||
self.data(0x00)
|
||||
self.data(0x00)
|
||||
self.data(0x4E)
|
||||
self.data(0x00)
|
||||
|
||||
self.command(0x98)
|
||||
self.data(0x3e)
|
||||
self.data(0x07)
|
||||
|
||||
self.command(0x35)
|
||||
self.command(0x21)
|
||||
|
||||
self.command(0x11)
|
||||
time.sleep(0.12)
|
||||
self.command(0x29)
|
||||
time.sleep(0.02)
|
||||
|
||||
def SetWindows(self, Xstart, Ystart, Xend, Yend):
|
||||
#set the X coordinates
|
||||
self.command(0x2A)
|
||||
self.data(0x00) #Set the horizontal starting point to the high octet
|
||||
self.data(Xstart) #Set the horizontal starting point to the low octet
|
||||
self.data(0x00) #Set the horizontal end to the high octet
|
||||
self.data(Xend - 1) #Set the horizontal end to the low octet
|
||||
|
||||
#set the Y coordinates
|
||||
self.command(0x2B)
|
||||
self.data(0x00)
|
||||
self.data(Ystart)
|
||||
self.data(0x00)
|
||||
self.data(Yend - 1)
|
||||
|
||||
self.command(0x2C)
|
||||
|
||||
def ShowImage(self,Image):
|
||||
"""Set buffer to value of Python Imaging Library image."""
|
||||
"""Write display buffer to physical display"""
|
||||
imwidth, imheight = Image.size
|
||||
if imwidth != self.width or imheight != self.height:
|
||||
raise ValueError('Image must be same dimensions as display \
|
||||
({0}x{1}).' .format(self.width, self.height))
|
||||
img = self.np.asarray(Image)
|
||||
pix = self.np.zeros((self.width,self.height,2), dtype = self.np.uint8)
|
||||
pix[...,[0]] = self.np.add(self.np.bitwise_and(img[...,[0]],0xF8),self.np.right_shift(img[...,[1]],5))
|
||||
pix[...,[1]] = self.np.add(self.np.bitwise_and(self.np.left_shift(img[...,[1]],3),0xE0),self.np.right_shift(img[...,[2]],3))
|
||||
pix = pix.flatten().tolist()
|
||||
self.SetWindows ( 0, 0, self.width, self.height)
|
||||
#self.digital_write(self.DC_PIN,self.GPIO.HIGH)
|
||||
self.CS_PIN.value(Pin.LOW)
|
||||
self.DC_PIN.value(Pin.HIGH)
|
||||
#for i in range(0,len(pix),4096):
|
||||
# self.spi_writebyte(pix[i:i+4096])
|
||||
self.spi_writebyte(pix)
|
||||
self.CS_PIN.value(Pin.HIGH)
|
||||
|
||||
def clear(self):
|
||||
"""Clear contents of image buffer"""
|
||||
_buffer = [0xff]*(self.width * self.height * 2)
|
||||
self.SetWindows ( 0, 0, self.width, self.height)
|
||||
#self.digital_write(self.DC_PIN,self.GPIO.HIGH)
|
||||
self.CS_PIN.value(Pin.LOW)
|
||||
self.DC_PIN.value(Pin.HIGH)
|
||||
#for i in range(0,len(_buffer),4096):
|
||||
# self.spi_writebyte(_buffer[i:i+4096])
|
||||
self.spi_writebyte(_buffer)
|
||||
self.CS_PIN.value(Pin.HIGH)
|
||||
|
||||
21
examples/external/imu/LICENSE.txt
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2020 Mika Tuupola
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
0
examples/external/imu/__init__.py
vendored
Normal file
212
examples/external/imu/ak8963.py
vendored
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
# From https://github.com/tuupola/micropython-mpu9250 which is originally licensed : see below.
|
||||
# Minor changes to work on cpython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# Copyright (c) 2018-2020 Mika Tuupola
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copied of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
# https://github.com/tuupola/micropython-mpu9250
|
||||
# https://www.akm.com/akm/en/file/datasheet/AK8963C.pdf
|
||||
|
||||
"""
|
||||
MicroPython I2C driver for AK8963 magnetometer
|
||||
"""
|
||||
|
||||
__version__ = "0.3.0"
|
||||
|
||||
# pylint: disable=import-error
|
||||
#import ustruct
|
||||
import struct as ustruct
|
||||
import utime
|
||||
from machine import I2C, Pin
|
||||
from micropython import const
|
||||
# pylint: enable=import-error
|
||||
|
||||
_WIA = const(0x00)
|
||||
_HXL = const(0x03)
|
||||
_HXH = const(0x04)
|
||||
_HYL = const(0x05)
|
||||
_HYH = const(0x06)
|
||||
_HZL = const(0x07)
|
||||
_HZH = const(0x08)
|
||||
_ST2 = const(0x09)
|
||||
_CNTL1 = const(0x0a)
|
||||
_ASAX = const(0x10)
|
||||
_ASAY = const(0x11)
|
||||
_ASAZ = const(0x12)
|
||||
|
||||
_MODE_POWER_DOWN = 0b00000000
|
||||
MODE_SINGLE_MEASURE = 0b00000001
|
||||
MODE_CONTINOUS_MEASURE_1 = 0b00000010 # 8Hz
|
||||
MODE_CONTINOUS_MEASURE_2 = 0b00000110 # 100Hz
|
||||
MODE_EXTERNAL_TRIGGER_MEASURE = 0b00000100
|
||||
_MODE_SELF_TEST = 0b00001000
|
||||
_MODE_FUSE_ROM_ACCESS = 0b00001111
|
||||
|
||||
OUTPUT_14_BIT = 0b00000000
|
||||
OUTPUT_16_BIT = 0b00010000
|
||||
|
||||
_SO_14BIT = 0.6 # μT per digit when 14bit mode
|
||||
_SO_16BIT = 0.15 # μT per digit when 16bit mode
|
||||
|
||||
class AK8963:
|
||||
"""Class which provides interface to AK8963 magnetometer."""
|
||||
def __init__(
|
||||
self, i2c, address=0x0c,
|
||||
mode=MODE_CONTINOUS_MEASURE_1, output=OUTPUT_16_BIT,
|
||||
offset=(0, 0, 0), scale=(1, 1, 1)
|
||||
):
|
||||
self.i2c = i2c
|
||||
self.address = address
|
||||
self._offset = offset
|
||||
self._scale = scale
|
||||
|
||||
if 0x48 != self.whoami:
|
||||
raise RuntimeError("AK8963 not found in I2C bus.")
|
||||
|
||||
# Sensitivity adjustement values
|
||||
self._register_char(_CNTL1, _MODE_FUSE_ROM_ACCESS)
|
||||
asax = self._register_char(_ASAX)
|
||||
asay = self._register_char(_ASAY)
|
||||
asaz = self._register_char(_ASAZ)
|
||||
self._register_char(_CNTL1, _MODE_POWER_DOWN)
|
||||
|
||||
# Should wait atleast 100us before next mode
|
||||
self._adjustement = (
|
||||
(0.5 * (asax - 128)) / 128 + 1,
|
||||
(0.5 * (asay - 128)) / 128 + 1,
|
||||
(0.5 * (asaz - 128)) / 128 + 1
|
||||
)
|
||||
|
||||
# Power on
|
||||
self._register_char(_CNTL1, (mode | output))
|
||||
|
||||
if output is OUTPUT_16_BIT:
|
||||
self._so = _SO_16BIT
|
||||
else:
|
||||
self._so = _SO_14BIT
|
||||
|
||||
@property
|
||||
def magnetic(self):
|
||||
"""
|
||||
X, Y, Z axis micro-Tesla (uT) as floats.
|
||||
"""
|
||||
xyz = list(self._register_three_shorts(_HXL))
|
||||
self._register_char(_ST2) # Enable updating readings again
|
||||
|
||||
# Apply factory axial sensitivy adjustements
|
||||
xyz[0] *= self._adjustement[0]
|
||||
xyz[1] *= self._adjustement[1]
|
||||
xyz[2] *= self._adjustement[2]
|
||||
|
||||
# Apply output scale determined in constructor
|
||||
so = self._so
|
||||
xyz[0] *= so
|
||||
xyz[1] *= so
|
||||
xyz[2] *= so
|
||||
|
||||
# Apply hard iron ie. offset bias from calibration
|
||||
xyz[0] -= self._offset[0]
|
||||
xyz[1] -= self._offset[1]
|
||||
xyz[2] -= self._offset[2]
|
||||
|
||||
# Apply soft iron ie. scale bias from calibration
|
||||
xyz[0] *= self._scale[0]
|
||||
xyz[1] *= self._scale[1]
|
||||
xyz[2] *= self._scale[2]
|
||||
|
||||
return tuple(xyz)
|
||||
|
||||
@property
|
||||
def adjustement(self):
|
||||
return self._adjustement
|
||||
|
||||
@property
|
||||
def whoami(self):
|
||||
""" Value of the whoami register. """
|
||||
return self._register_char(_WIA)
|
||||
|
||||
def calibrate(self, count=256, delay=200):
|
||||
self._offset = (0, 0, 0)
|
||||
self._scale = (1, 1, 1)
|
||||
|
||||
reading = self.magnetic
|
||||
minx = maxx = reading[0]
|
||||
miny = maxy = reading[1]
|
||||
minz = maxz = reading[2]
|
||||
|
||||
while count:
|
||||
utime.sleep_ms(delay)
|
||||
reading = self.magnetic
|
||||
minx = min(minx, reading[0])
|
||||
maxx = max(maxx, reading[0])
|
||||
miny = min(miny, reading[1])
|
||||
maxy = max(maxy, reading[1])
|
||||
minz = min(minz, reading[2])
|
||||
maxz = max(maxz, reading[2])
|
||||
count -= 1
|
||||
|
||||
# Hard iron correction
|
||||
offset_x = (maxx + minx) / 2
|
||||
offset_y = (maxy + miny) / 2
|
||||
offset_z = (maxz + minz) / 2
|
||||
|
||||
self._offset = (offset_x, offset_y, offset_z)
|
||||
|
||||
# Soft iron correction
|
||||
avg_delta_x = (maxx - minx) / 2
|
||||
avg_delta_y = (maxy - miny) / 2
|
||||
avg_delta_z = (maxz - minz) / 2
|
||||
|
||||
avg_delta = (avg_delta_x + avg_delta_y + avg_delta_z) / 3
|
||||
|
||||
scale_x = avg_delta / avg_delta_x
|
||||
scale_y = avg_delta / avg_delta_y
|
||||
scale_z = avg_delta / avg_delta_z
|
||||
|
||||
self._scale = (scale_x, scale_y, scale_z)
|
||||
|
||||
return self._offset, self._scale
|
||||
|
||||
def _register_short(self, register, value=None, buf=bytearray(2)):
|
||||
if value is None:
|
||||
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||
return ustruct.unpack("<h", buf)[0]
|
||||
|
||||
ustruct.pack_into("<h", buf, 0, value)
|
||||
return self.i2c.writeto_mem(self.address, register, buf)
|
||||
|
||||
def _register_three_shorts(self, register, buf=bytearray(6)):
|
||||
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||
return ustruct.unpack("<hhh", buf)
|
||||
|
||||
def _register_char(self, register, value=None, buf=bytearray(1)):
|
||||
if value is None:
|
||||
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||
return buf[0]
|
||||
|
||||
ustruct.pack_into("<b", buf, 0, value)
|
||||
return self.i2c.writeto_mem(self.address, register, buf)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
pass
|
||||
223
examples/external/imu/mpu6500.py
vendored
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
# From https://github.com/tuupola/micropython-mpu9250 which is originally licensed : see below.
|
||||
# Minor changes to work on cpython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# Copyright (c) 2018-2020 Mika Tuupola
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copied of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
# https://github.com/tuupola/micropython-mpu9250
|
||||
|
||||
|
||||
"""
|
||||
MicroPython I2C driver for MPU6500 6-axis motion tracking device
|
||||
"""
|
||||
|
||||
__version__ = "0.3.0"
|
||||
|
||||
# pylint: disable=import-error
|
||||
#import ustruct
|
||||
import struct as ustruct
|
||||
import utime
|
||||
from machine import I2C, Pin
|
||||
from micropython import const
|
||||
# pylint: enable=import-error
|
||||
|
||||
_GYRO_CONFIG = const(0x1b)
|
||||
_ACCEL_CONFIG = const(0x1c)
|
||||
_ACCEL_CONFIG2 = const(0x1d)
|
||||
_ACCEL_XOUT_H = const(0x3b)
|
||||
_ACCEL_XOUT_L = const(0x3c)
|
||||
_ACCEL_YOUT_H = const(0x3d)
|
||||
_ACCEL_YOUT_L = const(0x3e)
|
||||
_ACCEL_ZOUT_H = const(0x3f)
|
||||
_ACCEL_ZOUT_L= const(0x40)
|
||||
_TEMP_OUT_H = const(0x41)
|
||||
_TEMP_OUT_L = const(0x42)
|
||||
_GYRO_XOUT_H = const(0x43)
|
||||
_GYRO_XOUT_L = const(0x44)
|
||||
_GYRO_YOUT_H = const(0x45)
|
||||
_GYRO_YOUT_L = const(0x46)
|
||||
_GYRO_ZOUT_H = const(0x47)
|
||||
_GYRO_ZOUT_L = const(0x48)
|
||||
_WHO_AM_I = const(0x75)
|
||||
|
||||
#_ACCEL_FS_MASK = const(0b00011000)
|
||||
ACCEL_FS_SEL_2G = const(0b00000000)
|
||||
ACCEL_FS_SEL_4G = const(0b00001000)
|
||||
ACCEL_FS_SEL_8G = const(0b00010000)
|
||||
ACCEL_FS_SEL_16G = const(0b00011000)
|
||||
|
||||
_ACCEL_SO_2G = 16384 # 1 / 16384 ie. 0.061 mg / digit
|
||||
_ACCEL_SO_4G = 8192 # 1 / 8192 ie. 0.122 mg / digit
|
||||
_ACCEL_SO_8G = 4096 # 1 / 4096 ie. 0.244 mg / digit
|
||||
_ACCEL_SO_16G = 2048 # 1 / 2048 ie. 0.488 mg / digit
|
||||
|
||||
#_GYRO_FS_MASK = const(0b00011000)
|
||||
GYRO_FS_SEL_250DPS = const(0b00000000)
|
||||
GYRO_FS_SEL_500DPS = const(0b00001000)
|
||||
GYRO_FS_SEL_1000DPS = const(0b00010000)
|
||||
GYRO_FS_SEL_2000DPS = const(0b00011000)
|
||||
|
||||
_GYRO_SO_250DPS = 131
|
||||
_GYRO_SO_500DPS = 62.5
|
||||
_GYRO_SO_1000DPS = 32.8
|
||||
_GYRO_SO_2000DPS = 16.4
|
||||
|
||||
_TEMP_SO = 333.87
|
||||
_TEMP_OFFSET = 21
|
||||
|
||||
SF_G = 1
|
||||
SF_M_S2 = 9.80665 # 1 g = 9.80665 m/s2 ie. standard gravity
|
||||
SF_DEG_S = 1
|
||||
SF_RAD_S = 0.017453292519943 # 1 deg/s is 0.017453292519943 rad/s
|
||||
|
||||
class MPU6500:
|
||||
"""Class which provides interface to MPU6500 6-axis motion tracking device."""
|
||||
def __init__(
|
||||
self, i2c, address=0x68,
|
||||
accel_fs=ACCEL_FS_SEL_2G, gyro_fs=GYRO_FS_SEL_250DPS,
|
||||
accel_sf=SF_M_S2, gyro_sf=SF_RAD_S,
|
||||
gyro_offset=(0, 0, 0)
|
||||
):
|
||||
self.i2c = i2c
|
||||
self.address = address
|
||||
|
||||
# 0x70 = standalone MPU6500, 0x71 = MPU6250 SIP
|
||||
if self.whoami not in [0x71, 0x70]:
|
||||
raise RuntimeError("MPU6500 not found in I2C bus.")
|
||||
|
||||
self._accel_so = self._accel_fs(accel_fs)
|
||||
self._gyro_so = self._gyro_fs(gyro_fs)
|
||||
self._accel_sf = accel_sf
|
||||
self._gyro_sf = gyro_sf
|
||||
self._gyro_offset = gyro_offset
|
||||
|
||||
@property
|
||||
def acceleration(self):
|
||||
"""
|
||||
Acceleration measured by the sensor. By default will return a
|
||||
3-tuple of X, Y, Z axis acceleration values in m/s^2 as floats. Will
|
||||
return values in g if constructor was provided `accel_sf=SF_M_S2`
|
||||
parameter.
|
||||
"""
|
||||
so = self._accel_so
|
||||
sf = self._accel_sf
|
||||
|
||||
xyz = self._register_three_shorts(_ACCEL_XOUT_H)
|
||||
return tuple([value / so * sf for value in xyz])
|
||||
|
||||
@property
|
||||
def gyro(self):
|
||||
"""
|
||||
X, Y, Z radians per second as floats.
|
||||
"""
|
||||
so = self._gyro_so
|
||||
sf = self._gyro_sf
|
||||
ox, oy, oz = self._gyro_offset
|
||||
|
||||
xyz = self._register_three_shorts(_GYRO_XOUT_H)
|
||||
xyz = [value / so * sf for value in xyz]
|
||||
|
||||
xyz[0] -= ox
|
||||
xyz[1] -= oy
|
||||
xyz[2] -= oz
|
||||
|
||||
return tuple(xyz)
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""
|
||||
Die temperature in celcius as a float.
|
||||
"""
|
||||
temp = self._register_short(_TEMP_OUT_H)
|
||||
return ((temp - _TEMP_OFFSET) / _TEMP_SO) + _TEMP_OFFSET
|
||||
|
||||
@property
|
||||
def whoami(self):
|
||||
""" Value of the whoami register. """
|
||||
return self._register_char(_WHO_AM_I)
|
||||
|
||||
def calibrate(self, count=256, delay=0):
|
||||
ox, oy, oz = (0.0, 0.0, 0.0)
|
||||
self._gyro_offset = (0.0, 0.0, 0.0)
|
||||
n = float(count)
|
||||
|
||||
while count:
|
||||
utime.sleep_ms(delay)
|
||||
gx, gy, gz = self.gyro
|
||||
ox += gx
|
||||
oy += gy
|
||||
oz += gz
|
||||
count -= 1
|
||||
|
||||
self._gyro_offset = (ox / n, oy / n, oz / n)
|
||||
return self._gyro_offset
|
||||
|
||||
def _register_short(self, register, value=None, buf=bytearray(2)):
|
||||
if value is None:
|
||||
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||
return ustruct.unpack(">h", buf)[0]
|
||||
|
||||
ustruct.pack_into(">h", buf, 0, value)
|
||||
return self.i2c.writeto_mem(self.address, register, buf)
|
||||
|
||||
def _register_three_shorts(self, register, buf=bytearray(6)):
|
||||
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||
return ustruct.unpack(">hhh", buf)
|
||||
|
||||
def _register_char(self, register, value=None, buf=bytearray(1)):
|
||||
if value is None:
|
||||
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||
return buf[0]
|
||||
|
||||
ustruct.pack_into("<b", buf, 0, value)
|
||||
return self.i2c.writeto_mem(self.address, register, buf)
|
||||
|
||||
def _accel_fs(self, value):
|
||||
self._register_char(_ACCEL_CONFIG, value)
|
||||
|
||||
# Return the sensitivity divider
|
||||
if ACCEL_FS_SEL_2G == value:
|
||||
return _ACCEL_SO_2G
|
||||
elif ACCEL_FS_SEL_4G == value:
|
||||
return _ACCEL_SO_4G
|
||||
elif ACCEL_FS_SEL_8G == value:
|
||||
return _ACCEL_SO_8G
|
||||
elif ACCEL_FS_SEL_16G == value:
|
||||
return _ACCEL_SO_16G
|
||||
|
||||
def _gyro_fs(self, value):
|
||||
self._register_char(_GYRO_CONFIG, value)
|
||||
|
||||
# Return the sensitivity divider
|
||||
if GYRO_FS_SEL_250DPS == value:
|
||||
return _GYRO_SO_250DPS
|
||||
elif GYRO_FS_SEL_500DPS == value:
|
||||
return _GYRO_SO_500DPS
|
||||
elif GYRO_FS_SEL_1000DPS == value:
|
||||
return _GYRO_SO_1000DPS
|
||||
elif GYRO_FS_SEL_2000DPS == value:
|
||||
return _GYRO_SO_2000DPS
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
pass
|
||||
104
examples/external/imu/mpu9250.py
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# From https://github.com/tuupola/micropython-mpu9250 which is originally licensed : see below.
|
||||
# Minor changes to work on cpython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# Copyright (c) 2018-2020 Mika Tuupola
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copied of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
# https://github.com/tuupola/micropython-mpu9250
|
||||
|
||||
"""
|
||||
MicroPython I2C driver for MPU9250 9-axis motion tracking device
|
||||
"""
|
||||
|
||||
# pylint: disable=import-error
|
||||
from micropython import const
|
||||
from .mpu6500 import MPU6500
|
||||
from .ak8963 import AK8963
|
||||
# pylint: enable=import-error
|
||||
|
||||
__version__ = "0.3.0"
|
||||
|
||||
# Used for enabling and disabling the I2C bypass access
|
||||
_INT_PIN_CFG = const(0x37)
|
||||
_I2C_BYPASS_MASK = const(0b00000010)
|
||||
_I2C_BYPASS_EN = const(0b00000010)
|
||||
_I2C_BYPASS_DIS = const(0b00000000)
|
||||
|
||||
class MPU9250:
|
||||
"""Class which provides interface to MPU9250 9-axis motion tracking device."""
|
||||
def __init__(self, i2c, mpu6500 = None, ak8963 = None):
|
||||
if mpu6500 is None:
|
||||
self.mpu6500 = MPU6500(i2c)
|
||||
else:
|
||||
self.mpu6500 = mpu6500
|
||||
|
||||
# Enable I2C bypass to access AK8963 directly.
|
||||
char = self.mpu6500._register_char(_INT_PIN_CFG)
|
||||
char &= ~_I2C_BYPASS_MASK # clear I2C bits
|
||||
char |= _I2C_BYPASS_EN
|
||||
self.mpu6500._register_char(_INT_PIN_CFG, char)
|
||||
|
||||
if ak8963 is None:
|
||||
self.ak8963 = AK8963(i2c)
|
||||
else:
|
||||
self.ak8963 = ak8963
|
||||
|
||||
@property
|
||||
def acceleration(self):
|
||||
"""
|
||||
Acceleration measured by the sensor. By default will return a
|
||||
3-tuple of X, Y, Z axis values in m/s^2 as floats. To get values in g
|
||||
pass `accel_fs=SF_G` parameter to the MPU6500 constructor.
|
||||
"""
|
||||
return self.mpu6500.acceleration
|
||||
|
||||
@property
|
||||
def gyro(self):
|
||||
"""
|
||||
Gyro measured by the sensor. By default will return a 3-tuple of
|
||||
X, Y, Z axis values in rad/s as floats. To get values in deg/s pass
|
||||
`gyro_sf=SF_DEG_S` parameter to the MPU6500 constructor.
|
||||
"""
|
||||
return self.mpu6500.gyro
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""
|
||||
Die temperature in celcius as a float.
|
||||
"""
|
||||
return self.mpu6500.temperature
|
||||
|
||||
@property
|
||||
def magnetic(self):
|
||||
"""
|
||||
X, Y, Z axis micro-Tesla (uT) as floats.
|
||||
"""
|
||||
return self.ak8963.magnetic
|
||||
|
||||
@property
|
||||
def whoami(self):
|
||||
return self.mpu6500.whoami
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
pass
|
||||
BIN
examples/external/ressources/Font/Font00.ttf
vendored
Normal file
BIN
examples/external/ressources/Font/Font01.ttf
vendored
Normal file
BIN
examples/external/ressources/Font/Font02.ttf
vendored
Normal file
53
examples/external/ressources/Font/readme_CN.txt
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*****************************************************************************
|
||||
* | File : Readme_CN.txt
|
||||
* | Author : Waveshare team
|
||||
* | Function : Help with use
|
||||
* | Info :
|
||||
*----------------
|
||||
* | This version: V1.0
|
||||
* | Date : 2020-06-17
|
||||
* | Info : 在这里提供一个中文版本的使用文档,以便你的快速使用
|
||||
******************************************************************************/
|
||||
这个文件是帮助您使用本例程。
|
||||
|
||||
1.基本信息:
|
||||
本例程使用单独LCD模块进行了验证,你可以在工程的Examples\中查看对应的测试例程;
|
||||
本例程均在Raspberry Pi 4B上进行了验证;
|
||||
|
||||
2.管脚连接:
|
||||
管脚连接你可以在 \lib\lcdconfig.py中查看,这里也再重述一次:
|
||||
EPD => RPI(BCM)
|
||||
VCC -> 5V
|
||||
GND -> GND
|
||||
DIN -> 10(SPI0_MOSI)
|
||||
CLK -> 11(SPI0_SCK)
|
||||
CS -> 8(CE0)
|
||||
DC -> 25
|
||||
RST -> 27
|
||||
BL -> 18
|
||||
|
||||
3.安装库:
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python-pip
|
||||
sudo apt-get install python-pil
|
||||
sudo apt-get install python-numpy
|
||||
sudo pip install RPi.GPIO
|
||||
|
||||
或
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python3-pip
|
||||
sudo apt-get install python3-pil
|
||||
sudo apt-get install python3-numpy
|
||||
sudo pip3 install RPi.GPIO
|
||||
|
||||
4.基本使用:
|
||||
由于本工程是一个综合工程,对于使用而言,你可能需要阅读以下内容:
|
||||
你可以在examples\目录中查看测试程序
|
||||
请注意你购买的是哪一款的LCD模块。
|
||||
栗子:
|
||||
如果你购买的1.54inch LCD,那么你应该执行命令:
|
||||
sudo python ./1inch54_LCD_test.py
|
||||
|
||||
|
||||
BIN
examples/external/ressources/pic/LCD_1inch28_1.jpg
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
examples/external/ressources/pic/LCD_1inch28_2.jpg
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
examples/external/ressources/pic/LCD_1inch28_3.jpg
vendored
Normal file
|
After Width: | Height: | Size: 19 KiB |
53
examples/external/ressources/pic/readme_CN.txt
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*****************************************************************************
|
||||
* | File : Readme_CN.txt
|
||||
* | Author : Waveshare team
|
||||
* | Function : Help with use
|
||||
* | Info :
|
||||
*----------------
|
||||
* | This version: V1.0
|
||||
* | Date : 2020-06-17
|
||||
* | Info : 在这里提供一个中文版本的使用文档,以便你的快速使用
|
||||
******************************************************************************/
|
||||
这个文件是帮助您使用本例程。
|
||||
|
||||
1.基本信息:
|
||||
本例程使用单独LCD模块进行了验证,你可以在工程的Examples\中查看对应的测试例程;
|
||||
本例程均在Raspberry Pi 4B上进行了验证;
|
||||
|
||||
2.管脚连接:
|
||||
管脚连接你可以在 \lib\lcdconfig.py中查看,这里也再重述一次:
|
||||
EPD => RPI(BCM)
|
||||
VCC -> 5V
|
||||
GND -> GND
|
||||
DIN -> 10(SPI0_MOSI)
|
||||
CLK -> 11(SPI0_SCK)
|
||||
CS -> 8(CE0)
|
||||
DC -> 25
|
||||
RST -> 27
|
||||
BL -> 18
|
||||
|
||||
3.安装库:
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python-pip
|
||||
sudo apt-get install python-pil
|
||||
sudo apt-get install python-numpy
|
||||
sudo pip install RPi.GPIO
|
||||
|
||||
或
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python3-pip
|
||||
sudo apt-get install python3-pil
|
||||
sudo apt-get install python3-numpy
|
||||
sudo pip3 install RPi.GPIO
|
||||
|
||||
4.基本使用:
|
||||
由于本工程是一个综合工程,对于使用而言,你可能需要阅读以下内容:
|
||||
你可以在examples\目录中查看测试程序
|
||||
请注意你购买的是哪一款的LCD模块。
|
||||
栗子:
|
||||
如果你购买的1.54inch LCD,那么你应该执行命令:
|
||||
sudo python ./1inch54_LCD_test.py
|
||||
|
||||
|
||||
98
examples/external/rotary.py
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# From https://github.com/mivallion/Encoder which is originally licensed : see below
|
||||
# Somes changes to work on u2if module. Mainly to have the input states according to their
|
||||
# event (rising & falling). Indeed, with the u2if module, the code is not executed
|
||||
# on the microcontroller but in a remote way.
|
||||
# ********************************************************************************************************
|
||||
|
||||
"""
|
||||
Encoder library for Raspberry Pi for measuring quadrature encoded signals.
|
||||
created by Mivallion <mivallion@gmail.com>
|
||||
Version 1.0 - 01 april 2020 - inital release
|
||||
"""
|
||||
|
||||
#import RPi.GPIO as GPIO
|
||||
from machine import Pin
|
||||
|
||||
|
||||
class Encoder(object):
|
||||
"""
|
||||
Encoder class allows to work with rotary encoder
|
||||
which connected via two pin A and B.
|
||||
Works only on interrupts because all RPi pins allow that.
|
||||
This library is a simple port of the Arduino Encoder library
|
||||
(https://github.com/PaulStoffregen/Encoder)
|
||||
"""
|
||||
def __init__(self, A, B):
|
||||
#GPIO.setmode(GPIO.BCM)
|
||||
#GPIO.setup(A, GPIO.IN)
|
||||
#GPIO.setup(B, GPIO.IN)
|
||||
self.pinA = A
|
||||
self.pinB = B
|
||||
|
||||
self.pinA_value = self.pinA.value()
|
||||
self.pinB_value = self.pinB.value()
|
||||
|
||||
self.pos = 0
|
||||
self.state = 0
|
||||
if self.pinA_value:
|
||||
self.state |= 1
|
||||
if self.pinB_value:
|
||||
self.state |= 2
|
||||
|
||||
#GPIO.add_event_detect(A, GPIO.BOTH, callback=self.__update)
|
||||
#GPIO.add_event_detect(B, GPIO.BOTH, callback=self.__update)
|
||||
self.pinA.irq(handler=self.__update, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)
|
||||
self.pinB.irq(handler=self.__update, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)
|
||||
|
||||
# Get update state from their event. Do not get state from pin.value() because with the interruptions latency,
|
||||
# they will no longer have the right value
|
||||
def _update_input_value(self, pin, event):
|
||||
is_rising = event & Pin.IRQ_RISING
|
||||
is_falling = event & Pin.IRQ_FALLING
|
||||
|
||||
if event == 0x03:
|
||||
return
|
||||
|
||||
if pin == self.pinA.id:
|
||||
if self.pinA_value == Pin.HIGH and is_falling:
|
||||
self.pinA_value = Pin.LOW
|
||||
elif self.pinA_value == Pin.LOW and is_rising:
|
||||
self.pinA_value = Pin.HIGH
|
||||
elif pin == self.pinB.id :
|
||||
if self.pinB_value == Pin.HIGH and is_falling:
|
||||
self.pinB_value = Pin.LOW
|
||||
elif self.pinB_value == Pin.LOW and is_rising:
|
||||
self.pinB_value = Pin.HIGH
|
||||
|
||||
|
||||
"""
|
||||
update() calling every time when value on A or B pins changes.
|
||||
It updates the current position based on previous and current states
|
||||
of the rotary encoder.
|
||||
"""
|
||||
def __update(self, pin, event):
|
||||
self._update_input_value(pin, event)
|
||||
|
||||
state = self.state & 3
|
||||
if self.pinA_value:
|
||||
state |= 4
|
||||
if self.pinB_value:
|
||||
state |= 8
|
||||
|
||||
self.state = state >> 2
|
||||
|
||||
if state == 1 or state == 7 or state == 8 or state == 14:
|
||||
self.pos += 1
|
||||
elif state == 2 or state == 4 or state == 11 or state == 13:
|
||||
self.pos -= 1
|
||||
elif state == 3 or state == 12:
|
||||
self.pos += 2
|
||||
elif state == 6 or state == 9:
|
||||
self.pos -= 2
|
||||
|
||||
|
||||
"""
|
||||
read() simply returns the current position of the rotary encoder.
|
||||
"""
|
||||
def read(self):
|
||||
return self.pos
|
||||
297
examples/external/ssd1306.py
vendored
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
# From https://github.com/adafruit/Adafruit_CircuitPython_SSD1306 which is originally licensed : see below.
|
||||
# Minor changes to work on micropython
|
||||
# ********************************************************************************************************
|
||||
|
||||
# SPDX-FileCopyrightText: 2017 Michael McWethy for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
`adafruit_ssd1306`
|
||||
====================================================
|
||||
|
||||
MicroPython SSD1306 OLED driver, I2C and SPI interfaces
|
||||
|
||||
* Author(s): Tony DiCola, Michael McWethy
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from micropython import const
|
||||
#from adafruit_bus_device import i2c_device, spi_device
|
||||
|
||||
try:
|
||||
import framebuf
|
||||
except ImportError:
|
||||
import adafruit_framebuf as framebuf
|
||||
|
||||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SSD1306.git"
|
||||
|
||||
# register definitions
|
||||
SET_CONTRAST = const(0x81)
|
||||
SET_ENTIRE_ON = const(0xA4)
|
||||
SET_NORM_INV = const(0xA6)
|
||||
SET_DISP = const(0xAE)
|
||||
SET_MEM_ADDR = const(0x20)
|
||||
SET_COL_ADDR = const(0x21)
|
||||
SET_PAGE_ADDR = const(0x22)
|
||||
SET_DISP_START_LINE = const(0x40)
|
||||
SET_SEG_REMAP = const(0xA0)
|
||||
SET_MUX_RATIO = const(0xA8)
|
||||
SET_COM_OUT_DIR = const(0xC0)
|
||||
SET_DISP_OFFSET = const(0xD3)
|
||||
SET_COM_PIN_CFG = const(0xDA)
|
||||
SET_DISP_CLK_DIV = const(0xD5)
|
||||
SET_PRECHARGE = const(0xD9)
|
||||
SET_VCOM_DESEL = const(0xDB)
|
||||
SET_CHARGE_PUMP = const(0x8D)
|
||||
|
||||
|
||||
class _SSD1306(framebuf.FrameBuffer):
|
||||
"""Base class for SSD1306 display driver"""
|
||||
|
||||
# pylint: disable-msg=too-many-arguments
|
||||
def __init__(self, buffer, width, height, *, external_vcc, reset):
|
||||
super().__init__(buffer, width, height)
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.external_vcc = external_vcc
|
||||
# reset may be None if not needed
|
||||
self.reset_pin = reset
|
||||
if self.reset_pin:
|
||||
self.reset_pin.value(0)
|
||||
self.pages = self.height // 8
|
||||
# Note the subclass must initialize self.framebuf to a framebuffer.
|
||||
# This is necessary because the underlying data buffer is different
|
||||
# between I2C and SPI implementations (I2C needs an extra byte).
|
||||
self._power = False
|
||||
self.poweron()
|
||||
self.init_display()
|
||||
|
||||
@property
|
||||
def power(self):
|
||||
"""True if the display is currently powered on, otherwise False"""
|
||||
return self._power
|
||||
|
||||
def init_display(self):
|
||||
"""Base class to initialize display"""
|
||||
# The various screen sizes available with the ssd1306 OLED driver
|
||||
# chip require differing configuration values for the display clock
|
||||
# div and com pin, which are listed below for reference and future
|
||||
# compatibility:
|
||||
# w, h: DISP_CLK_DIV COM_PIN_CFG
|
||||
# 128, 64: 0x80 0x12
|
||||
# 128, 32: 0x80 0x02
|
||||
# 96, 16: 0x60 0x02
|
||||
# 64, 48: 0x80 0x12
|
||||
# 64, 32: 0x80 0x12
|
||||
for cmd in (
|
||||
SET_DISP | 0x00, # off
|
||||
# address setting
|
||||
SET_MEM_ADDR,
|
||||
0x00, # horizontal
|
||||
# resolution and layout
|
||||
SET_DISP_START_LINE | 0x00,
|
||||
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
|
||||
SET_MUX_RATIO,
|
||||
self.height - 1,
|
||||
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
|
||||
SET_DISP_OFFSET,
|
||||
0x00,
|
||||
SET_COM_PIN_CFG,
|
||||
0x02
|
||||
if (self.height == 32 or self.height == 16) and (self.width != 64)
|
||||
else 0x12,
|
||||
# timing and driving scheme
|
||||
SET_DISP_CLK_DIV,
|
||||
0x80,
|
||||
SET_PRECHARGE,
|
||||
0x22 if self.external_vcc else 0xF1,
|
||||
SET_VCOM_DESEL,
|
||||
0x30, # 0.83*Vcc
|
||||
# display
|
||||
SET_CONTRAST,
|
||||
0xFF, # maximum
|
||||
SET_ENTIRE_ON, # output follows RAM contents
|
||||
SET_NORM_INV, # not inverted
|
||||
# charge pump
|
||||
SET_CHARGE_PUMP,
|
||||
0x10 if self.external_vcc else 0x14,
|
||||
SET_DISP | 0x01,
|
||||
): # on
|
||||
self.write_cmd(cmd)
|
||||
if self.width == 72:
|
||||
self.write_cmd(0xAD)
|
||||
self.write_cmd(0x30)
|
||||
self.fill(0)
|
||||
self.show()
|
||||
|
||||
def poweroff(self):
|
||||
"""Turn off the display (nothing visible)"""
|
||||
self.write_cmd(SET_DISP | 0x00)
|
||||
self._power = False
|
||||
|
||||
def contrast(self, contrast):
|
||||
"""Adjust the contrast"""
|
||||
self.write_cmd(SET_CONTRAST)
|
||||
self.write_cmd(contrast)
|
||||
|
||||
def invert(self, invert):
|
||||
"""Invert all pixels on the display"""
|
||||
self.write_cmd(SET_NORM_INV | (invert & 1))
|
||||
|
||||
def write_framebuf(self):
|
||||
"""Derived class must implement this"""
|
||||
raise NotImplementedError
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
"""Derived class must implement this"""
|
||||
raise NotImplementedError
|
||||
|
||||
def poweron(self):
|
||||
"Reset device and turn on the display."
|
||||
if self.reset_pin:
|
||||
self.reset_pin.value(1)
|
||||
time.sleep(0.001)
|
||||
self.reset_pin.value(0)
|
||||
time.sleep(0.010)
|
||||
self.reset_pin.value(1)
|
||||
time.sleep(0.010)
|
||||
self.write_cmd(SET_DISP | 0x01)
|
||||
self._power = True
|
||||
|
||||
def show(self):
|
||||
"""Update the display"""
|
||||
xpos0 = 0
|
||||
xpos1 = self.width - 1
|
||||
if self.width == 64:
|
||||
# displays with width of 64 pixels are shifted by 32
|
||||
xpos0 += 32
|
||||
xpos1 += 32
|
||||
if self.width == 72:
|
||||
# displays with width of 72 pixels are shifted by 28
|
||||
xpos0 += 28
|
||||
xpos1 += 28
|
||||
self.write_cmd(SET_COL_ADDR)
|
||||
self.write_cmd(xpos0)
|
||||
self.write_cmd(xpos1)
|
||||
self.write_cmd(SET_PAGE_ADDR)
|
||||
self.write_cmd(0)
|
||||
self.write_cmd(self.pages - 1)
|
||||
self.write_framebuf()
|
||||
|
||||
|
||||
class SSD1306_I2C(_SSD1306):
|
||||
"""
|
||||
I2C class for SSD1306
|
||||
|
||||
:param width: the width of the physical screen in pixels,
|
||||
:param height: the height of the physical screen in pixels,
|
||||
:param i2c: the I2C peripheral to use,
|
||||
:param addr: the 8-bit bus address of the device,
|
||||
:param external_vcc: whether external high-voltage source is connected.
|
||||
:param reset: if needed, DigitalInOut designating reset pin
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, width, height, i2c, *, addr=0x3C, external_vcc=False, reset=None
|
||||
):
|
||||
#self.i2c_device = i2c_device.I2CDevice(i2c, addr)
|
||||
self.i2c = i2c
|
||||
self.addr = addr
|
||||
self.temp = bytearray(2)
|
||||
# Add an extra byte to the data buffer to hold an I2C data/command byte
|
||||
# to use hardware-compatible I2C transactions. A memoryview of the
|
||||
# buffer is used to mask this byte from the framebuffer operations
|
||||
# (without a major memory hit as memoryview doesn't copy to a separate
|
||||
# buffer).
|
||||
self.buffer = bytearray(((height // 8) * width) + 1)
|
||||
self.buffer[0] = 0x40 # Set first byte of data buffer to Co=0, D/C=1
|
||||
super().__init__(
|
||||
memoryview(self.buffer)[1:],
|
||||
width,
|
||||
height,
|
||||
external_vcc=external_vcc,
|
||||
reset=reset,
|
||||
)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
"""Send a command to the SPI device"""
|
||||
self.temp[0] = 0x80 # Co=1, D/C#=0
|
||||
self.temp[1] = cmd
|
||||
#with self.i2c_device:
|
||||
# self.i2c_device.write(self.temp)
|
||||
self.i2c.writeto(self.addr, self.temp)
|
||||
|
||||
def write_framebuf(self):
|
||||
"""Blast out the frame buffer using a single I2C transaction to support
|
||||
hardware I2C interfaces."""
|
||||
#with self.i2c_device:
|
||||
# self.i2c_device.write(self.buffer)
|
||||
self.i2c.writeto(self.addr, self.buffer)
|
||||
|
||||
|
||||
# pylint: disable-msg=too-many-arguments
|
||||
class SSD1306_SPI(_SSD1306):
|
||||
"""
|
||||
SPI class for SSD1306
|
||||
|
||||
:param width: the width of the physical screen in pixels,
|
||||
:param height: the height of the physical screen in pixels,
|
||||
:param spi: the SPI peripheral to use,
|
||||
:param dc: the data/command pin to use (often labeled "D/C"),
|
||||
:param reset: the reset pin to use,
|
||||
:param cs: the chip-select pin to use (sometimes labeled "SS").
|
||||
"""
|
||||
|
||||
# pylint: disable=no-member
|
||||
# Disable should be reconsidered when refactor can be tested.
|
||||
def __init__(
|
||||
self,
|
||||
width,
|
||||
height,
|
||||
spi,
|
||||
dc,
|
||||
reset,
|
||||
cs,
|
||||
*,
|
||||
external_vcc=False,
|
||||
baudrate=8000000,
|
||||
polarity=0,
|
||||
phase=0
|
||||
):
|
||||
self.rate = 10 * 1024 * 1024
|
||||
dc.value(0)
|
||||
#self.spi_device = spi_device.SPIDevice(
|
||||
# spi, cs, baudrate=baudrate, polarity=polarity, phase=phase
|
||||
#)
|
||||
self.spi_device = spi
|
||||
self.dc_pin = dc
|
||||
self.cs_pin = cs
|
||||
self.buffer = bytearray((height // 8) * width)
|
||||
super().__init__(
|
||||
memoryview(self.buffer),
|
||||
width,
|
||||
height,
|
||||
external_vcc=external_vcc,
|
||||
reset=reset,
|
||||
)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
"""Send a command to the SPI device"""
|
||||
self.dc_pin.value(0)
|
||||
#with self.spi_device as spi:
|
||||
# spi.write(bytearray([cmd]))
|
||||
self.cs_pin.value(0)
|
||||
self.spi_device.write(bytearray([cmd]))
|
||||
self.cs_pin.value(1)
|
||||
|
||||
def write_framebuf(self):
|
||||
"""write to the frame buffer via SPI"""
|
||||
self.dc_pin.value(1)
|
||||
#with self.spi_device as spi:
|
||||
# spi.write(self.buffer)
|
||||
self.cs_pin.value(0)
|
||||
self.spi_device.write(self.buffer)
|
||||
self.cs_pin.value(1)
|
||||
8
examples/i2c_scan.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from machine import I2C, SPI, u2if, Pin
|
||||
|
||||
# Run a scan on the second I2C (i2_index=1)
|
||||
|
||||
|
||||
i2c = I2C(i2c_index=0, frequency=400000) # , pullup=True
|
||||
slaves = i2c.scan()
|
||||
print("i2c slaves found %s" % slaves)
|
||||
20
examples/imu_mpu9250_i2c.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# From https://github.com/tuupola/micropython-mpu9250
|
||||
# Minor changes to work with u2if module
|
||||
|
||||
import time
|
||||
from machine import I2C, Pin
|
||||
from external.imu.mpu9250 import MPU9250
|
||||
|
||||
i2c = I2C(i2c_index=0, frequency=400000) # , pullup=True
|
||||
sensor = MPU9250(i2c)
|
||||
|
||||
print("MPU9250 id: " + hex(sensor.whoami))
|
||||
|
||||
while True:
|
||||
print(sensor.acceleration)
|
||||
print(sensor.gyro)
|
||||
print(sensor.magnetic)
|
||||
print(sensor.temperature)
|
||||
|
||||
#time.sleep(1)
|
||||
time.sleep(0.1)
|
||||
99
examples/lcd_ball_ssd1306_spi.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Example and ssd1306 driver derived from https://github.com/adafruit/Adafruit_CircuitPython_SSD1306, whhich is licensed :
|
||||
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
from external.ssd1306 import SSD1306_SPI, SET_DISP_START_LINE
|
||||
from machine import SPI, Pin, u2if
|
||||
|
||||
|
||||
# Connect an I2C SSD1306 SPI (128x64)
|
||||
# Pinout:
|
||||
# GND: GND
|
||||
# VCC: +3.3v
|
||||
# D0: SPI0_CLK
|
||||
# D1: SPI0_MOSI
|
||||
# RES: GP_8
|
||||
# DC: GP_9
|
||||
# CS: SPI0_CS1
|
||||
|
||||
spi = SPI(spi_index=0)
|
||||
spi.init(baudrate=10000000)
|
||||
|
||||
reset = Pin(u2if.GP_8, Pin.OUT, value=Pin.LOW)
|
||||
dc = Pin(u2if.GP_9, Pin.OUT, value=Pin.LOW)
|
||||
cs = Pin(u2if.SPI0_CS1, Pin.OUT, value=Pin.HIGH)
|
||||
|
||||
oled = SSD1306_SPI(128, 64, spi, dc, reset, cs)
|
||||
|
||||
# Helper function to draw a circle from a given position with a given radius
|
||||
# This is an implementation of the midpoint circle algorithm,
|
||||
# see https://en.wikipedia.org/wiki/Midpoint_circle_algorithm#C_example for details
|
||||
def draw_circle(xpos0, ypos0, rad, col=1):
|
||||
x = rad - 1
|
||||
y = 0
|
||||
dx = 1
|
||||
dy = 1
|
||||
err = dx - (rad << 1)
|
||||
while x >= y:
|
||||
oled.pixel(xpos0 + x, ypos0 + y, col)
|
||||
oled.pixel(xpos0 + y, ypos0 + x, col)
|
||||
oled.pixel(xpos0 - y, ypos0 + x, col)
|
||||
oled.pixel(xpos0 - x, ypos0 + y, col)
|
||||
oled.pixel(xpos0 - x, ypos0 - y, col)
|
||||
oled.pixel(xpos0 - y, ypos0 - x, col)
|
||||
oled.pixel(xpos0 + y, ypos0 - x, col)
|
||||
oled.pixel(xpos0 + x, ypos0 - y, col)
|
||||
if err <= 0:
|
||||
y += 1
|
||||
err += dy
|
||||
dy += 2
|
||||
if err > 0:
|
||||
x -= 1
|
||||
dx += 2
|
||||
err += dx - (rad << 1)
|
||||
|
||||
|
||||
# initial center of the circle
|
||||
center_x = 63
|
||||
center_y = 15
|
||||
# how fast does it move in each direction
|
||||
x_inc = 1
|
||||
y_inc = 1
|
||||
# what is the starting radius of the circle
|
||||
radius = 8
|
||||
|
||||
# start with a blank screen
|
||||
oled.fill(0)
|
||||
# we just blanked the framebuffer. to push the framebuffer onto the display, we call show()
|
||||
oled.show()
|
||||
while True:
|
||||
# undraw the previous circle
|
||||
draw_circle(center_x, center_y, radius, col=0)
|
||||
|
||||
# if bouncing off right
|
||||
if center_x + radius >= oled.width:
|
||||
# start moving to the left
|
||||
x_inc = -1
|
||||
# if bouncing off left
|
||||
elif center_x - radius < 0:
|
||||
# start moving to the right
|
||||
x_inc = 1
|
||||
|
||||
# if bouncing off top
|
||||
if center_y + radius >= oled.height:
|
||||
# start moving down
|
||||
y_inc = -1
|
||||
# if bouncing off bottom
|
||||
elif center_y - radius < 0:
|
||||
# start moving up
|
||||
y_inc = 1
|
||||
|
||||
# go more in the current direction
|
||||
center_x += x_inc
|
||||
center_y += y_inc
|
||||
|
||||
# draw the new circle
|
||||
draw_circle(center_x, center_y, radius)
|
||||
# show all the changes we just made
|
||||
oled.show()
|
||||
66
examples/lcd_time_ssd1306_i2c.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Example and ssd1306 driver derived from https://github.com/adafruit/Adafruit_CircuitPython_SSD1306, which is licensed :
|
||||
# SPDX-FileCopyrightText: Melissa LeBlanc-Williams for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from external.ssd1306 import SSD1306_I2C, SET_DISP_START_LINE
|
||||
from machine import I2C
|
||||
|
||||
# Connect an I2C SSD1306 LCD (128x64)
|
||||
|
||||
|
||||
def show_image(display, image, draw, font, font2):
|
||||
# write the current time to the display after each scroll
|
||||
draw.rectangle((0, 0, display.width, display.height * 2), outline=0, fill=0)
|
||||
text = time.strftime("%A")
|
||||
draw.text((0, 0), text, font=font, fill=255)
|
||||
text = time.strftime("%e %b %Y")
|
||||
draw.text((0, 14), text, font=font, fill=255)
|
||||
text = time.strftime("%X")
|
||||
draw.text((0, 36), text, font=font2, fill=255)
|
||||
display.image(image)
|
||||
display.show()
|
||||
|
||||
|
||||
# Use second I2C port
|
||||
i2c = I2C(i2c_index=1, frequency=400000) # , pullup=True
|
||||
|
||||
display = SSD1306_I2C(128, 64, i2c)
|
||||
# Clear the display. Always call show after changing pixels to make the display
|
||||
# update visible!
|
||||
display.fill(0)
|
||||
display.show()
|
||||
time.sleep(0.5)
|
||||
display.fill(1)
|
||||
display.show()
|
||||
time.sleep(0.5)
|
||||
display.fill(0)
|
||||
display.show()
|
||||
|
||||
# # Set a pixel in the origin 0,0 position.
|
||||
# display.pixel(0, 0, 1)
|
||||
# # Set a pixel in the middle 64, 16 position.
|
||||
# display.pixel(64, 32, 1)
|
||||
# # Set a pixel in the opposite 127, 31 position.
|
||||
# display.pixel(127, 63, 1)
|
||||
# display.show()
|
||||
image = Image.new("1", (display.width, display.height))
|
||||
draw = ImageDraw.Draw(image)
|
||||
|
||||
# Load a font in 2 different sizes.
|
||||
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 16)
|
||||
font2 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 24)
|
||||
offset = 0 # flips between 0 and 32 for double buffering
|
||||
|
||||
|
||||
while True:
|
||||
for i in range(0, display.height // 2):
|
||||
offset = (offset + 1) % display.height
|
||||
display.write_cmd(SET_DISP_START_LINE | offset)
|
||||
show_image(display, image, draw, font, font2)
|
||||
|
||||
for i in range(0, display.height // 2):
|
||||
show_image(display, image, draw, font, font2)
|
||||
time.sleep(0.05)
|
||||
|
||||
16
examples/led_pwm.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import time
|
||||
from machine import u2if, Pin, PWM
|
||||
|
||||
led_pwm = PWM(Pin(u2if.GP_3))
|
||||
led_pwm.freq(1000)
|
||||
|
||||
while True:
|
||||
for i in range(0, 65535, 50):
|
||||
led_pwm.duty_u16(i)
|
||||
time.sleep(0.005)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
for i in reversed(range(0, 65535, 50)):
|
||||
led_pwm.duty_u16(i)
|
||||
time.sleep(0.005)
|
||||
5
examples/machine_info.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import machine
|
||||
|
||||
print('S/N: %s' % machine.unique_id())
|
||||
print('V/N: %s' % machine.firmware_version())
|
||||
|
||||
21
examples/pin_input.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import time
|
||||
from machine import u2if, Pin, Signal
|
||||
|
||||
|
||||
def get_state_string(value):
|
||||
return "LOW" if value == Pin.LOW else "HIGH"
|
||||
|
||||
|
||||
switch = Pin(u2if.GP_9, Pin.IN, pull=Pin.PULL_UP)
|
||||
|
||||
for _ in range(10):
|
||||
input_value = switch.value()
|
||||
print("switch state : %s" % get_state_string(input_value))
|
||||
time.sleep(1)
|
||||
|
||||
switch_invert = Signal(Pin(u2if.GP_8, Pin.IN, pull=Pin.PULL_UP), invert=True)
|
||||
|
||||
for _ in range(10):
|
||||
input_value = switch_invert.value()
|
||||
print("switch (inverted) state : %s" % get_state_string(input_value))
|
||||
time.sleep(1)
|
||||
27
examples/pin_input_irq_debounce.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import time
|
||||
from machine import u2if, Pin
|
||||
|
||||
|
||||
def irq_callback(pin, event=None):
|
||||
is_rising = event & Pin.IRQ_RISING
|
||||
is_falling = event & Pin.IRQ_FALLING
|
||||
info_interrupt = '%s pin %d =>' % (time.time()*1000, pin)
|
||||
if is_rising:
|
||||
info_interrupt += ' RISING'
|
||||
if is_falling:
|
||||
info_interrupt += ' FALLING'
|
||||
print(info_interrupt)
|
||||
|
||||
|
||||
# Configure first switch
|
||||
switch = Pin(u2if.GP_9, Pin.IN, pull=Pin.PULL_UP)
|
||||
switch.irq(handler=irq_callback, trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING)
|
||||
# Configure second switch with debouncer
|
||||
switch_debounced = Pin(u2if.GP_8, Pin.IN, pull=Pin.PULL_UP)
|
||||
switch_debounced.irq(handler=irq_callback, trigger=Pin.IRQ_FALLING, debounce=True)
|
||||
|
||||
while True:
|
||||
# Retrieve all irq recorded and call handler
|
||||
Pin.process_irq()
|
||||
time.sleep(0.005)
|
||||
|
||||
24
examples/pin_led.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import time
|
||||
from machine import u2if, Pin, Signal
|
||||
|
||||
# Initialize GPIO to output and set the value HIGH
|
||||
led = Pin(u2if.GP_3, Pin.OUT, value=Pin.HIGH)
|
||||
time.sleep(1)
|
||||
# Switch off the led
|
||||
led.value(Pin.LOW)
|
||||
|
||||
|
||||
# Active-low RGB led
|
||||
led_r = Signal(Pin(u2if.GP_6, Pin.OUT), invert=True)
|
||||
led_g = Signal(Pin(u2if.GP_7, Pin.OUT), invert=True)
|
||||
led_b = Signal(Pin(u2if.GP_8, Pin.OUT), invert=True)
|
||||
|
||||
# Switch on the three colors
|
||||
led_r.value(Pin.HIGH)
|
||||
led_g.on() # == .value(Pin.HIGH)
|
||||
led_b.on()
|
||||
time.sleep(1)
|
||||
# Switch off the three colors
|
||||
led_r.off()
|
||||
led_g.value(Pin.LOW) # == .value(Pin.LOW)
|
||||
led_b.value(Pin.LOW)
|
||||
8
examples/read_analog.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import time
|
||||
from machine import u2if, ADC
|
||||
|
||||
analog = ADC(u2if.GP26_ADC0)
|
||||
|
||||
while True:
|
||||
print('Analog GP26_ADC0: %d' % analog.value())
|
||||
time.sleep(1)
|
||||
35
examples/rotary_encoder.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import time
|
||||
from external.rotary import Encoder
|
||||
from machine import Pin, u2if
|
||||
|
||||
# This example uses a rotary encore from www.diymore.cc.
|
||||
# S1 and S2 are debounced in hardware
|
||||
# S1, S2 and Key are pulled-high.
|
||||
# GND: GND
|
||||
# Vcc : 3.3v
|
||||
# S1: GP_21
|
||||
# S2: GP_22
|
||||
# Key: GP_28
|
||||
|
||||
|
||||
def irq_callback(pin, event=None):
|
||||
if pin == u2if.GP_28 and event == Pin.IRQ_FALLING:
|
||||
print("Key pressed")
|
||||
|
||||
|
||||
s1 = Pin(u2if.GP_21, Pin.IN)
|
||||
s2 = Pin(u2if.GP_22, Pin.IN)
|
||||
|
||||
encoder = Encoder(s1, s2)
|
||||
key = Pin(u2if.GP_28, Pin.IN)
|
||||
key.irq(handler=irq_callback, trigger=Pin.IRQ_FALLING, debounce=True) # software debounced in u2if
|
||||
|
||||
last_value = encoder.read()
|
||||
while True:
|
||||
# Retrieve all irq recorded and call handler
|
||||
Pin.process_irq()
|
||||
value = encoder.read()
|
||||
if last_value != value:
|
||||
print("Encoder value: %d" % value)
|
||||
last_value = value
|
||||
time.sleep(0.005)
|
||||
85
examples/round_lcd_gc9a01.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# Round lcd GC9A01 (240x240) example, from Waveshare team. Modified to work on micropython
|
||||
|
||||
#import chardet
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
from external.gc9a01 import Lcd
|
||||
from PIL import Image, ImageDraw,ImageFont
|
||||
from machine import SPI, Pin, u2if
|
||||
|
||||
try:
|
||||
# display with hardware SPI:
|
||||
''' Warning!!!Don't creation of multiple displayer objects!!! '''
|
||||
#disp = LCD_1inch28.LCD_1inch28(spi=SPI.SpiDev(bus, device),spi_freq=10000000,rst=RST,dc=DC,bl=BL)
|
||||
spi = SPI(spi_index=0)
|
||||
spi.init(baudrate=1000000)
|
||||
|
||||
rst = Pin(u2if.GP_6)
|
||||
dc = Pin(u2if.GP_7)
|
||||
cs = Pin(u2if.GP_8)
|
||||
bl = Pin(u2if.GP_9)
|
||||
|
||||
disp = Lcd(spi, dc, rst, cs, bl, bl_freq=1000)
|
||||
# Initialize library.
|
||||
disp.Init()
|
||||
disp.bl_DutyCycle(65000)
|
||||
# Clear display.
|
||||
disp.clear()
|
||||
|
||||
# Create blank image for drawing.
|
||||
image1 = Image.new("RGB", (disp.width, disp.height), "BLACK")
|
||||
draw = ImageDraw.Draw(image1)
|
||||
|
||||
#logging.info("draw point")
|
||||
#draw.rectangle((Xstart,Ystart,Xend,Yend), fill = "color")
|
||||
print("draw circle")
|
||||
draw.arc((1,1,239,239),0, 360, fill =(0,0,255))
|
||||
draw.arc((2,2,238,238),0, 360, fill =(0,0,255))
|
||||
draw.arc((3,3,237,237),0, 360, fill =(0,0,255))
|
||||
|
||||
print("draw dial line")
|
||||
draw.line([(120, 1),(120, 12)], fill = (128,255,128),width = 4)
|
||||
draw.line([(120, 227),(120, 239)], fill = (128,255,128),width = 4)
|
||||
draw.line([(1,120),(12,120)], fill = (128,255,128),width = 4)
|
||||
draw.line([(227,120),(239,120)], fill = (128,255,128),width = 4)
|
||||
|
||||
# print("draw text")
|
||||
Font1 = ImageFont.truetype("./external/ressources/Font/Font01.ttf",25)
|
||||
Font2 = ImageFont.truetype("./external/ressources/Font/Font01.ttf",35)
|
||||
Font3 = ImageFont.truetype("./external/ressources/Font/Font02.ttf",32)
|
||||
#
|
||||
draw.text((40, 50), 'WaveShare', fill = (128,255,128),font=Font2)
|
||||
text= u"微雪电子"
|
||||
draw.text((74, 150),text, fill = "WHITE",font=Font3)
|
||||
|
||||
print("draw pointer line")
|
||||
draw.line([(120, 120),(70, 70)], fill = "YELLOW",width = 3)
|
||||
draw.line([(120, 120),(176, 64)], fill = "BLUE",width = 3)
|
||||
draw.line([(120, 120),(120 ,210)], fill = "RED",width = 3)
|
||||
|
||||
# im_r=image1.rotate(180)
|
||||
# disp.ShowImage(im_r)
|
||||
disp.ShowImage(image1)
|
||||
time.sleep(3)
|
||||
print("show image")
|
||||
image = Image.open('./external/ressources/pic/LCD_1inch28_1.jpg')
|
||||
#im_r=image.rotate(180)
|
||||
#disp.ShowImage(im_r)
|
||||
disp.ShowImage(image)
|
||||
time.sleep(3)
|
||||
#disp.module_exit()
|
||||
#logging.info("quit:")
|
||||
print("quit")
|
||||
except IOError as e:
|
||||
#logging.info(e)
|
||||
print(e)
|
||||
except KeyboardInterrupt:
|
||||
disp.module_exit()
|
||||
#logging.info("quit:")
|
||||
print("quit:")
|
||||
exit()
|
||||
8
examples/select_interface.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import machine
|
||||
|
||||
# if there are multiple u2if connected, we must specify its serial number by this command before using it.
|
||||
# Test with your id (use machine_info.py test program to get it)
|
||||
machine.select_interface("0xE66038B713644F31")
|
||||
|
||||
print('S/N: %s' % machine.unique_id())
|
||||
print('V/N: %s' % machine.firmware_version())
|
||||
25
examples/servo_pwm.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import time
|
||||
from machine import u2if, Pin, PWM
|
||||
|
||||
# Connect a servo on GP_6
|
||||
|
||||
MIN_DUTY_MS = 1000
|
||||
MAX_DUTY_MS = 2000
|
||||
|
||||
servo_pwm = PWM(Pin(u2if.GP_6))
|
||||
servo_pwm.freq(50)
|
||||
|
||||
duty = MIN_DUTY_MS
|
||||
direction = 1
|
||||
|
||||
while True:
|
||||
duty += direction
|
||||
if duty > MAX_DUTY_MS:
|
||||
duty = MAX_DUTY_MS
|
||||
direction = -direction
|
||||
elif duty < MIN_DUTY_MS:
|
||||
duty = MIN_DUTY_MS
|
||||
direction = -direction
|
||||
servo_pwm.duty_ns(duty*1000)
|
||||
time.sleep(0.005)
|
||||
|
||||
48
examples/temp_bmp280_i2c_spi.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Example and BMP280 driver derived from https://github.com/adafruit/Adafruit_CircuitPython_BMP280 which is licensed:
|
||||
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
|
||||
# # SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
from external.bmp280 import *
|
||||
from machine import I2C, SPI, u2if, Pin
|
||||
|
||||
|
||||
# Connect a BMP280 in I2C (index 0) :
|
||||
# VCC: 3.3v
|
||||
# GND: GND
|
||||
# SCL: I2C0_SCL
|
||||
# SDA: I2C0_SDA
|
||||
#i2c = I2C(i2c_index=0, frequency=400000) # , pullup=True
|
||||
#bmp280 = Adafruit_BMP280_I2C(i2c, 0x76)
|
||||
|
||||
# or in SPI:
|
||||
# VCC: 3.3v
|
||||
# GND: GND
|
||||
# SCL: SPI0_CLK
|
||||
# SDA: SPI0_MOSI (=SDI)
|
||||
# CSB: SPI0_CS1
|
||||
# SDO: SPI0_MISO
|
||||
spi = SPI(spi_index=0)
|
||||
spi.init(baudrate=10000000)
|
||||
cs = Pin(u2if.SPI0_CS1, Pin.OUT, value=Pin.HIGH)
|
||||
bmp280 = Adafruit_BMP280_SPI(spi, cs)
|
||||
|
||||
|
||||
|
||||
# change this to match the location's pressure (hPa) at sea level
|
||||
bmp280.sea_level_pressure = 1013.25
|
||||
bmp280.mode = MODE_NORMAL
|
||||
bmp280.standby_period = STANDBY_TC_500
|
||||
bmp280.iir_filter = IIR_FILTER_X16
|
||||
bmp280.overscan_pressure = OVERSCAN_X16
|
||||
bmp280.overscan_temperature = OVERSCAN_X2
|
||||
# The sensor will need a moment to gather inital readings
|
||||
time.sleep(1)
|
||||
|
||||
while True:
|
||||
print("\nTemperature: %0.1f C" % bmp280.temperature)
|
||||
print("Pressure: %0.1f hPa" % bmp280.pressure)
|
||||
print("Altitude = %0.2f meters" % bmp280.altitude)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
53
examples/uart_rw.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import time
|
||||
from machine import UART
|
||||
|
||||
# Connect a USB to UART (CP2102, FT232, ...) to PICO UART (GP_0, GP_1) and open terminal on it (putty, ...)
|
||||
uart = UART()
|
||||
uart.init(115200)
|
||||
|
||||
fable = bytearray("""\r\nLa Cigale, ayant chanté\r
|
||||
Tout l'été,\r
|
||||
Se trouva fort dépourvue\r
|
||||
Quand la bise fut venue :\r
|
||||
Pas un seul petit morceau\r
|
||||
De mouche ou de vermisseau.\r
|
||||
Elle alla crier famine\r
|
||||
Chez la Fourmi sa voisine,\r
|
||||
La priant de lui prêter\r
|
||||
Quelque grain pour subsister\r
|
||||
Jusqu'à la saison nouvelle.\r
|
||||
"Je vous paierai, lui dit-elle,\r
|
||||
Avant l'Oût, foi d'animal,\r
|
||||
Intérêt et principal. "\r
|
||||
La Fourmi n'est pas prêteuse :\r
|
||||
C'est là son moindre défaut.\r
|
||||
Que faisiez-vous au temps chaud ?\r
|
||||
Dit-elle à cette emprunteuse.\r
|
||||
- Nuit et jour à tout venant\r
|
||||
Je chantais, ne vous déplaise.\r
|
||||
- Vous chantiez ? j'en suis fort aise.\r
|
||||
Eh bien! dansez maintenant.\r\r\n
|
||||
Fable de Jean de la Fontaine\n""".encode())
|
||||
|
||||
uart.write(fable)
|
||||
time.sleep(1)
|
||||
|
||||
uart.write("\r\nType character on terminal\r\n".encode())
|
||||
|
||||
while True:
|
||||
buf = uart.read(5, timeout=10)
|
||||
# buf = uart.read(5)
|
||||
# buf = uart.read()
|
||||
# buf = uart.readline()
|
||||
# buf = uart.readline(0)
|
||||
# buf = uart.readline(10)
|
||||
# buf2 = [0, 0, 0, 0, 0, 0]
|
||||
# uart.readinto(buf2, 4, 10)
|
||||
# uart.readinto(buf2, timeout=10)
|
||||
|
||||
if len(buf) == 0:
|
||||
print("No data")
|
||||
else:
|
||||
print(buf)
|
||||
|
||||
print("Remaining bytes in UART : %d" % uart.any())
|
||||
57
examples/vl53l0x_interrupt.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Example and vl53l0x driver derived from https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_VL53L0X which is licensed:
|
||||
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
|
||||
from external import adafruit_vl53l0x
|
||||
from machine import I2C, Pin, u2if
|
||||
|
||||
# Demo of the VL53L0X distance sensor with interrupt.
|
||||
# There are two mode:
|
||||
# * Manual: user set low GP_9 (button with pull up) => trigger a measure
|
||||
# * Auto: read measure as fast as it can.
|
||||
# Module interrupt has to be wired to GP_13 and button if needed, to GP_9
|
||||
|
||||
mode_auto = False # Set False to manual trigger with GP_9
|
||||
start_measure = True
|
||||
|
||||
|
||||
def irq_callback(pin, event=None):
|
||||
global start_measure
|
||||
is_falling = event & Pin.IRQ_FALLING
|
||||
if pin == u2if.GP13_SPI1_CS1 and is_falling:
|
||||
print("Range: {0}mm".format(vl53.read_measure()))
|
||||
start_measure = mode_auto
|
||||
elif pin == u2if.GP_9 and is_falling:
|
||||
start_measure = True
|
||||
|
||||
|
||||
# Initialize I2C bus and sensor. Use first I2C port.
|
||||
i2c = I2C(i2c_index=0, frequency=400000) # , pullup=True
|
||||
int_pin = Pin(u2if.GP13_SPI1_CS1, Pin.IN)
|
||||
int_pin.irq(handler=irq_callback, trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING)
|
||||
button_pin = Pin(u2if.GP_9, Pin.IN)
|
||||
button_pin.irq(handler=irq_callback, trigger=Pin.IRQ_FALLING, debounce=True)
|
||||
vl53 = adafruit_vl53l0x.VL53L0X(i2c)
|
||||
|
||||
|
||||
# Optionally adjust the measurement timing budget to change speed and accuracy.
|
||||
# See the example here for more details:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/examples/Single/Single.ino
|
||||
# For example a higher speed but less accurate timing budget of 20ms:
|
||||
# vl53.measurement_timing_budget = 20000
|
||||
# Or a slower but more accurate timing budget of 200ms:
|
||||
# vl53.measurement_timing_budget = 200000
|
||||
# The default timing budget is 33ms, a good compromise of speed and accuracy.
|
||||
|
||||
vl53.measurement_timing_budget = 100000
|
||||
|
||||
# Main loop will read the range and print it every second.
|
||||
while True:
|
||||
if start_measure:
|
||||
vl53.start_measure()
|
||||
start_measure = False
|
||||
|
||||
Pin.process_irq()
|
||||
time.sleep(0.005)
|
||||
29
examples/vl53l0x_simpletest.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Example and vl53l0x driver derived from https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_VL53L0X which is licensed:
|
||||
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Simple demo of the VL53L0X distance sensor.
|
||||
# Will print the sensed range/distance every second.
|
||||
import time
|
||||
|
||||
from external import adafruit_vl53l0x
|
||||
from machine import I2C
|
||||
|
||||
# Initialize I2C bus and sensor. Use first I2C port.
|
||||
i2c = I2C(i2c_index=0, frequency=400000) # , pullup=True
|
||||
vl53 = adafruit_vl53l0x.VL53L0X(i2c)
|
||||
|
||||
|
||||
# Optionally adjust the measurement timing budget to change speed and accuracy.
|
||||
# See the example here for more details:
|
||||
# https://github.com/pololu/vl53l0x-arduino/blob/master/examples/Single/Single.ino
|
||||
# For example a higher speed but less accurate timing budget of 20ms:
|
||||
# vl53.measurement_timing_budget = 20000
|
||||
# Or a slower but more accurate timing budget of 200ms:
|
||||
# vl53.measurement_timing_budget = 200000
|
||||
# The default timing budget is 33ms, a good compromise of speed and accuracy.
|
||||
|
||||
# Main loop will read the range and print it every second.
|
||||
while True:
|
||||
print("Range: {0}mm".format(vl53.range))
|
||||
time.sleep(1.0)
|
||||
0
firmware/.gitignore
vendored
Normal file
34
firmware/README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# u2if PICO firmware
|
||||
|
||||
C++ firmware of the PICO to work with the u2if python module.
|
||||
Binary file (u2if.uf2) is available in published release and to must be uploaded to the pico. It can be also be built.
|
||||
|
||||
## Upload method
|
||||
Plug in the PICO while holding down the BOOTSEL button, then a USB flash storage should appear. Copy "u2if.uf2" on it.
|
||||
|
||||
## Working
|
||||
The firmware makes the pico act like a USB device (generic HID and CDC). Each command is blocking and is done via the HID interface (64 byte report). For some operations, CDC is used to increase the transfer speed.
|
||||
|
||||
## Linux: UDEV rule
|
||||
To make PICO with this firmware usable in non-root mode, add the following file (/etc/udev/rules.d/55-hid.rules):
|
||||
|
||||
```bash
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="cafe", ATTR{idProduct}=="4005", MODE="0666"
|
||||
```
|
||||
|
||||
## Build firmware
|
||||
|
||||
In u2if/firmware/, clone pico-sdk (v1.1.0):
|
||||
- git clone https://github.com/raspberrypi/pico-sdk.git
|
||||
- cd pico-sdk
|
||||
- git reset --hard 1.1.0
|
||||
- git submodule update --init
|
||||
|
||||
In u2if/firmware/source directory:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make
|
||||
|
||||
The firmware to upload to Pico is u2if/firmware/source/build/u2if.uf2
|
||||
|
||||
45
firmware/source/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
# Set PICO_SDK_PATH to parent directory
|
||||
get_filename_component(PICO_SDK_PATH "${CMAKE_CURRENT_LIST_DIR}/../pico-sdk" ABSOLUTE)
|
||||
|
||||
# initialize the SDK based on PICO_SDK_PATH
|
||||
# note: this must happen before project()
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
project(u2if VERSION "0.1.0")
|
||||
|
||||
# initialize the Pico SDK
|
||||
pico_sdk_init()
|
||||
|
||||
# Enable wanted peripherals
|
||||
set(I2C0_ENABLE 1)
|
||||
set(I2C1_ENABLE 1)
|
||||
set(SPI0_ENABLE 1)
|
||||
set(SPI1_ENABLE 1)
|
||||
set(UART_ENABLE 1)
|
||||
set(PWM_ENABLE 1)
|
||||
set(ADC_ENABLE 1)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_SOURCE_DIR}/config.h")
|
||||
|
||||
FILE(GLOB InterfaceSources interfaces/*.cpp)
|
||||
|
||||
add_executable(u2if
|
||||
main.cpp
|
||||
usb_descriptors.c
|
||||
ModeActivity.cpp
|
||||
${InterfaceSources}
|
||||
)
|
||||
|
||||
target_include_directories(u2if PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
target_link_libraries(u2if PRIVATE pico_stdlib pico_unique_id tinyusb_device tinyusb_board
|
||||
hardware_i2c hardware_watchdog hardware_pwm hardware_adc hardware_spi)
|
||||
|
||||
pico_enable_stdio_usb(u2if 0)
|
||||
pico_enable_stdio_uart(u2if 0) # Set to 1, call stdio_init_all(); to make printf for debugging puroposes
|
||||
|
||||
pico_add_extra_outputs(u2if)
|
||||
|
||||
# add url via pico_set_program_url
|
||||
#example_auto_set_url(u2if)
|
||||
114
firmware/source/LICENSE
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
Project u2if (firmware for raspberry pico):
|
||||
-------------------------------------------
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 execuc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
|
||||
External project licenses:
|
||||
--------------------------
|
||||
|
||||
-------------------
|
||||
Raspberry Pico SDK:
|
||||
-------------------
|
||||
|
||||
Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--------
|
||||
TinyUsb:
|
||||
--------
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018, hathach (tinyusb.org)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------
|
||||
MicroPython (for rp2040 pwm):
|
||||
------------ ----------------
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020-2021 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
75
firmware/source/ModeActivity.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "ModeActivity.h"
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
// Activity led
|
||||
const uint8_t LED_PIN = 25;
|
||||
DeviceState ModeActivity::_sDeviceState = DeviceState::NOT_MOUNTED;
|
||||
repeating_timer_t ModeActivity::_sLedTimer;
|
||||
uint32_t ModeActivity::_sBlinkPeriodCount;
|
||||
// CONST
|
||||
const int32_t LED_TASK_PERIODS_MS = 50;
|
||||
const uint32_t NOT_MOUNTED_STATE_PERIODS_MS = 1000;
|
||||
const uint32_t SUSPENDED_STATE_PERIODS_MS = 2500;
|
||||
|
||||
|
||||
ModeActivity::ModeActivity() {
|
||||
_sDeviceState = DeviceState::NOT_MOUNTED;
|
||||
_sBlinkPeriodCount = 0;
|
||||
}
|
||||
|
||||
ModeActivity::~ModeActivity() {
|
||||
|
||||
}
|
||||
|
||||
void ModeActivity::init() {
|
||||
// init activity led and timer
|
||||
gpio_init(LED_PIN);
|
||||
gpio_set_dir(LED_PIN, true);
|
||||
gpio_put(LED_PIN, false);
|
||||
add_repeating_timer_ms(-LED_TASK_PERIODS_MS, ledTask, NULL, &_sLedTimer);
|
||||
}
|
||||
|
||||
void ModeActivity::setDeviceState(DeviceState deviceState) {
|
||||
_sDeviceState = deviceState;
|
||||
if(_sDeviceState == DeviceState::MOUNTED) {
|
||||
_sBlinkPeriodCount = 10;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceState ModeActivity::getDeviceState() {
|
||||
return _sDeviceState;
|
||||
}
|
||||
|
||||
void ModeActivity::setBlinking() {
|
||||
_sBlinkPeriodCount = 2;
|
||||
}
|
||||
|
||||
void ModeActivity::setBlinkingInfinite() {
|
||||
_sBlinkPeriodCount = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
bool ModeActivity::ledTask(repeating_timer_t *rt) {
|
||||
(void)rt;
|
||||
static bool led_state = false;
|
||||
static uint32_t periodCounter = 0;
|
||||
|
||||
if(_sDeviceState == DeviceState::SUSPENDED || _sDeviceState == DeviceState::NOT_MOUNTED) {
|
||||
led_state = !!(periodCounter == 0);
|
||||
|
||||
if(++periodCounter > (_sDeviceState == DeviceState::SUSPENDED ? SUSPENDED_STATE_PERIODS_MS/LED_TASK_PERIODS_MS : NOT_MOUNTED_STATE_PERIODS_MS/LED_TASK_PERIODS_MS))
|
||||
periodCounter = 0;
|
||||
} else if(_sDeviceState == DeviceState::MOUNTED) {
|
||||
if(_sBlinkPeriodCount > 0) {
|
||||
led_state = 1 - led_state;
|
||||
_sBlinkPeriodCount--;
|
||||
} else {
|
||||
led_state = false;
|
||||
}
|
||||
} else {
|
||||
led_state = 1 - led_state;
|
||||
}
|
||||
gpio_put(LED_PIN, led_state);
|
||||
|
||||
return true;
|
||||
}
|
||||
33
firmware/source/ModeActivity.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _MODE_ACTIVITY_H
|
||||
#define _MODE_ACTIVITY_H
|
||||
|
||||
#include "pico/time.h"
|
||||
|
||||
// USB Device state
|
||||
enum DeviceState {
|
||||
NOT_MOUNTED = 1,
|
||||
MOUNTED = 2,
|
||||
SUSPENDED = 3
|
||||
};
|
||||
|
||||
class ModeActivity {
|
||||
public:
|
||||
ModeActivity();
|
||||
~ModeActivity();
|
||||
|
||||
void init();
|
||||
static void setDeviceState(DeviceState deviceState);
|
||||
static DeviceState getDeviceState();
|
||||
static void setBlinking();
|
||||
static void setBlinkingInfinite();
|
||||
|
||||
protected:
|
||||
static bool ledTask(repeating_timer_t *rt);
|
||||
static DeviceState _sDeviceState;
|
||||
static repeating_timer_t _sLedTimer;
|
||||
static uint32_t _sBlinkPeriodCount;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
19
firmware/source/config.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _U2IF_CONFIG_H
|
||||
#define _U2IF_CONFIG_H
|
||||
|
||||
#define PROJECT_NAME "u2if"
|
||||
#define PROJECT_VER "0.1.0"
|
||||
#define PROJECT_VER_MAJOR 0
|
||||
#define PROJECT_VER_MINOR 1
|
||||
#define PROJECT_VER_PATCH 0
|
||||
|
||||
#define I2C0_ENABLED 1
|
||||
#define I2C1_ENABLED 1
|
||||
#define SPI0_ENABLED 1
|
||||
#define SPI1_ENABLED 1
|
||||
#define UART_ENABLED 1
|
||||
#define PWM_ENABLED 1
|
||||
#define ADC_ENABLED 1
|
||||
#define GPIO_ENABLED 1
|
||||
|
||||
#endif // _U2IF_CONFIG_H
|
||||
66
firmware/source/interfaces/Adc.cpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include "Adc.h"
|
||||
#include "hardware/adc.h"
|
||||
|
||||
Adc::Adc() {
|
||||
setInterfaceState(InterfaceState::INTIALIZED);
|
||||
adc_init();
|
||||
}
|
||||
|
||||
Adc::~Adc() {
|
||||
|
||||
}
|
||||
|
||||
CmdStatus Adc::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
|
||||
if(cmd[0] == Report::ID::ADC_INIT_PIN) {
|
||||
status = gpioInit(cmd);
|
||||
} else if(cmd[0] == Report::ID::ADC_GET_VALUE) {
|
||||
status = getValue(cmd, response);
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus Adc::task(uint8_t response[64]) {
|
||||
(void)response;
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int8_t Adc::getAdcIndexFromGpio(uint8_t gpio) {
|
||||
if(gpio < 26 || gpio > 28)
|
||||
return -1;
|
||||
else
|
||||
return (static_cast<int8_t>(gpio)-26);
|
||||
}
|
||||
|
||||
CmdStatus Adc::gpioInit(uint8_t const *cmd) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
const int adcIndex = getAdcIndexFromGpio(gpio);
|
||||
if(adcIndex >= 0) {
|
||||
adc_gpio_init(gpio);
|
||||
return CmdStatus::OK;
|
||||
} else {
|
||||
return CmdStatus::NOK;
|
||||
}
|
||||
}
|
||||
|
||||
CmdStatus Adc::getValue(uint8_t const *cmd, uint8_t response[64]) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
const int adcIndex = getAdcIndexFromGpio(gpio);
|
||||
|
||||
if(adcIndex >= 0) {
|
||||
adc_select_input(static_cast<uint>(adcIndex));
|
||||
uint16_t value_u16 = adc_read();
|
||||
response[2] = gpio;
|
||||
convertUInt16ToBytes(static_cast<uint16_t>(value_u16), &response[3]);
|
||||
return CmdStatus::OK;
|
||||
} else {
|
||||
return CmdStatus::NOK;
|
||||
}
|
||||
}
|
||||
|
||||
23
firmware/source/interfaces/Adc.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef _INTERFACE_ADC_H
|
||||
#define _INTERFACE_ADC_H
|
||||
|
||||
#include "PicoInterfacesBoard.h"
|
||||
#include "BaseInterface.h"
|
||||
|
||||
|
||||
class Adc : public BaseInterface {
|
||||
public:
|
||||
Adc();
|
||||
virtual ~Adc();
|
||||
|
||||
CmdStatus process(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus task(uint8_t response[64]);
|
||||
protected:
|
||||
static int8_t getAdcIndexFromGpio(uint8_t gpio);
|
||||
CmdStatus gpioInit(uint8_t const *cmd);
|
||||
CmdStatus getValue(uint8_t const *cmd, uint8_t response[64]);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
47
firmware/source/interfaces/BaseInterface.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include "BaseInterface.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "tusb.h"
|
||||
|
||||
|
||||
BaseInterface::BaseInterface() :
|
||||
_interfaceState(InterfaceState::NOT_INITIALIZED) {
|
||||
}
|
||||
|
||||
BaseInterface::~BaseInterface(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
CmdStatus BaseInterface::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
(void)cmd;
|
||||
(void)response;
|
||||
return CmdStatus::NOT_CONCERNED;
|
||||
}
|
||||
|
||||
CmdStatus BaseInterface::task(uint8_t response[64]) {
|
||||
(void)response;
|
||||
return CmdStatus::NOT_CONCERNED;
|
||||
}
|
||||
|
||||
void BaseInterface::convertUInt32ToBytes(uint32_t value, uint8_t *array) {
|
||||
array[0] = static_cast<uint8_t>(value & 0xFF);
|
||||
array[1] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
array[2] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
array[3] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
void BaseInterface::convertUInt16ToBytes(uint16_t value, uint8_t *array) {
|
||||
array[0] = static_cast<uint8_t>(value & 0xFF);
|
||||
array[1] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
uint32_t BaseInterface::convertBytesToUInt32(const uint8_t *array) {
|
||||
const uint32_t value = static_cast<uint32_t>(array[0]) | (static_cast<uint32_t>(array[1]) << 8u) | (static_cast<uint32_t>(array[2]) << 16u) | (static_cast<uint32_t>(array[3]) << 24u);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t BaseInterface::convertBytesToUInt16(const uint8_t *array) {
|
||||
const uint16_t value = static_cast<uint16_t>(array[0]) | (static_cast<uint16_t>(array[1]) << 8u);
|
||||
return value;
|
||||
}
|
||||
38
firmware/source/interfaces/BaseInterface.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _BASE_INTERFACES_PICO_H
|
||||
#define _BASE_INTERFACES_PICO_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "../tusb_config.h"
|
||||
|
||||
#include "PicoInterfacesBoard.h"
|
||||
|
||||
enum InterfaceState {
|
||||
NOT_INITIALIZED = 1,
|
||||
INTIALIZED = 2
|
||||
};
|
||||
|
||||
class BaseInterface {
|
||||
public:
|
||||
|
||||
BaseInterface();
|
||||
virtual ~BaseInterface();
|
||||
virtual CmdStatus process(uint8_t const *cmd, uint8_t response[64]);
|
||||
virtual CmdStatus task(uint8_t response[64]);
|
||||
inline InterfaceState getInterfaceState() const { return _interfaceState;}
|
||||
static void convertUInt32ToBytes(uint32_t value, uint8_t *array);
|
||||
static void convertUInt16ToBytes(uint16_t value, uint8_t *array);
|
||||
static uint32_t convertBytesToUInt32(const uint8_t *array);
|
||||
static uint16_t convertBytesToUInt16(const uint8_t *array);
|
||||
|
||||
protected:
|
||||
inline void setInterfaceState(InterfaceState interfaceState) {_interfaceState = interfaceState;}
|
||||
|
||||
|
||||
InterfaceState _interfaceState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
206
firmware/source/interfaces/Gpio.cpp
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
#include "Gpio.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
// à mettre en variables memebres ?
|
||||
static const uint8_t MAX_BUFFERED_EVENT = 60;
|
||||
static uint8_t irqEventBuffer[MAX_BUFFERED_EVENT];
|
||||
static volatile uint8_t irqEventBufferCount = 0;
|
||||
static critical_section_t critSec;
|
||||
|
||||
// Debouncer variables
|
||||
const uint8_t MAX_PINS = 30;
|
||||
const uint8_t DEBOUNCE_PERIODS_MS = 1;
|
||||
const uint8_t PRESS_PERIODS_MS = 3;
|
||||
const uint8_t RELEASE_PERIODS_MS = 20;
|
||||
static uint32_t debouncedEvtRisingList = 0x00;
|
||||
static uint32_t debouncedEvtFallingList = 0x00;
|
||||
static uint32_t debouncedStateList = 0x00;
|
||||
static uint8_t debouncerCounterList[MAX_PINS];
|
||||
|
||||
|
||||
void gpioCallback(uint gpio, uint32_t events) {
|
||||
uint8_t interfaceEvent = gpio & 0b00111111;
|
||||
if(events & GPIO_IRQ_EDGE_RISE)
|
||||
interfaceEvent |= IRQ_EVENT::EVENT_RISING << 6;
|
||||
if(events & GPIO_IRQ_EDGE_FALL)
|
||||
interfaceEvent |= IRQ_EVENT::EVENT_FALLING << 6;
|
||||
|
||||
critical_section_enter_blocking(&critSec);
|
||||
if(irqEventBufferCount < MAX_BUFFERED_EVENT) {
|
||||
irqEventBuffer[irqEventBufferCount++] = interfaceEvent;
|
||||
}
|
||||
critical_section_exit(&critSec);
|
||||
}
|
||||
|
||||
// debouncing : http://stackoverflow.com/questions/155071/simple-debounce-routine
|
||||
bool debounceInput(repeating_timer_t *rt) {
|
||||
(void)rt;
|
||||
|
||||
uint32_t rawStatePins = gpio_get_all();
|
||||
for(uint8_t gpio=0; gpio < MAX_PINS; gpio++){
|
||||
bool risingEv = !!(debouncedEvtRisingList & (1ul << gpio));
|
||||
bool fallingEv = !!(debouncedEvtFallingList & (1ul << gpio));
|
||||
if( !fallingEv && !risingEv)
|
||||
continue;
|
||||
|
||||
bool rawState = !!((1ul << gpio) & rawStatePins);
|
||||
bool debouncedState = debouncedStateList & (0x01 << gpio);
|
||||
if(rawState == debouncedState){
|
||||
if(debouncedState)
|
||||
debouncerCounterList[gpio] = RELEASE_PERIODS_MS / DEBOUNCE_PERIODS_MS;
|
||||
else
|
||||
debouncerCounterList[gpio] = PRESS_PERIODS_MS / DEBOUNCE_PERIODS_MS;
|
||||
} else {
|
||||
// Key has changed - wait for new state to become stable.
|
||||
if (--(debouncerCounterList[gpio]) == 0) {
|
||||
// Timer expired - accept the change.
|
||||
uint8_t interfaceEvent = 0x00;
|
||||
if(rawState) {
|
||||
debouncedStateList |= (1ul << gpio);
|
||||
debouncerCounterList[gpio] = RELEASE_PERIODS_MS / DEBOUNCE_PERIODS_MS;
|
||||
if(risingEv)
|
||||
interfaceEvent |= IRQ_EVENT::EVENT_RISING << 6;
|
||||
} else {
|
||||
debouncedStateList &= ~(1ul << gpio);
|
||||
debouncerCounterList[gpio] = PRESS_PERIODS_MS / DEBOUNCE_PERIODS_MS;
|
||||
if(fallingEv)
|
||||
interfaceEvent |= IRQ_EVENT::EVENT_FALLING << 6;
|
||||
}
|
||||
|
||||
if(interfaceEvent != 0x00) {
|
||||
interfaceEvent |= (gpio & 0b00111111);
|
||||
critical_section_enter_blocking(&critSec);
|
||||
if(irqEventBufferCount < MAX_BUFFERED_EVENT) {
|
||||
irqEventBuffer[irqEventBufferCount++] = interfaceEvent;
|
||||
}
|
||||
critical_section_exit(&critSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Gpio::Gpio() {
|
||||
setInterfaceState(InterfaceState::INTIALIZED);
|
||||
critical_section_init(&critSec);
|
||||
add_repeating_timer_us(-DEBOUNCE_PERIODS_MS * 1000, debounceInput, NULL, &_debounceTimer);
|
||||
}
|
||||
|
||||
Gpio::~Gpio() {
|
||||
}
|
||||
|
||||
CmdStatus Gpio::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
|
||||
if(cmd[0] == Report::ID::GPIO_INIT_PIN) {
|
||||
status = initPin(cmd);
|
||||
} else if(cmd[0] == Report::ID::GPIO_SET_VALUE) {
|
||||
status = setPin(cmd);
|
||||
} else if(cmd[0] == Report::ID::GPIO_GET_VALUE) {
|
||||
status = getPin(cmd, response);
|
||||
} else if(cmd[0] == Report::ID::GPIO_SET_IRQ) {
|
||||
status = setIrq(cmd);
|
||||
} else if(cmd[0] == Report::ID::GPIO_GET_IRQ) {
|
||||
status = getIrq(cmd, response);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus Gpio::task(uint8_t response[64]) {
|
||||
(void)response;
|
||||
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
CmdStatus Gpio::initPin(uint8_t const *cmd) {
|
||||
const uint gp = cmd[1];
|
||||
const uint dir = cmd[2] == 0 ? GPIO_IN : GPIO_OUT;
|
||||
gpio_init(gp);
|
||||
gpio_set_dir(gp, dir);
|
||||
|
||||
if(dir == GPIO_IN && cmd[3] == 1) {
|
||||
gpio_pull_up(gp);
|
||||
} else if(dir == GPIO_IN && cmd[3] == 2) {
|
||||
gpio_pull_down(gp);
|
||||
}
|
||||
//a voir gpio_set_outover(gpio, GPIO_OVERRIDE_INVERT);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Gpio::setPin(uint8_t const *cmd) {
|
||||
const uint gp = cmd[1];
|
||||
bool value = cmd[2] == 0 ? false : true;
|
||||
gpio_put(gp, value);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Gpio::getPin(uint8_t const *cmd, uint8_t response[64]) {
|
||||
const uint8_t gp = cmd[1];
|
||||
response[2] = gp;
|
||||
response[3] = gpio_get(gp);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Gpio::setIrq(uint8_t const *cmd) {
|
||||
const uint gpio = cmd[1];
|
||||
const uint8_t ev = cmd[2];
|
||||
bool debounced = cmd[3] == 0x01 ? true : false;
|
||||
uint8_t event_flags = 0;
|
||||
if(ev & IRQ_EVENT::EVENT_RISING)
|
||||
event_flags |= GPIO_IRQ_EDGE_RISE;
|
||||
if(ev & IRQ_EVENT::EVENT_FALLING)
|
||||
event_flags |= GPIO_IRQ_EDGE_FALL;
|
||||
|
||||
critical_section_enter_blocking(&critSec);
|
||||
// Remove previous irq settings if exists
|
||||
gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false);
|
||||
debouncedEvtFallingList &= ~(1ul << gpio);
|
||||
debouncedEvtRisingList &= ~(1ul << gpio);
|
||||
|
||||
if(event_flags != 0 && !debounced) {
|
||||
gpio_set_irq_enabled_with_callback(gpio, event_flags, true, gpioCallback);
|
||||
} else if(event_flags != 0) {
|
||||
if(ev & IRQ_EVENT::EVENT_FALLING)
|
||||
debouncedEvtFallingList |= 1ul << gpio;
|
||||
if(ev & IRQ_EVENT::EVENT_RISING)
|
||||
debouncedEvtRisingList |= 1ul << gpio;
|
||||
|
||||
if(gpio_get(gpio))
|
||||
debouncedStateList |= (0x01 << gpio);
|
||||
else
|
||||
debouncedStateList &= ~(1ul << gpio);
|
||||
}
|
||||
critical_section_exit(&critSec);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
// TODO: To rework, it is a simple version with buffer smaller than HID response.
|
||||
// It is necessary to be able to have larger buffers. Currently they are the size of the HID response.
|
||||
CmdStatus Gpio::getIrq(uint8_t const *cmd, uint8_t response[64]) {
|
||||
(void)cmd;
|
||||
static uint32_t eventBufferCopy[MAX_BUFFERED_EVENT];
|
||||
static uint8_t eventBufferCountCopy = 0;
|
||||
|
||||
if(eventBufferCountCopy == 0) {
|
||||
critical_section_enter_blocking(&critSec);
|
||||
eventBufferCountCopy = irqEventBufferCount;
|
||||
memcpy(eventBufferCopy, irqEventBuffer, sizeof(uint32_t) * eventBufferCountCopy);
|
||||
irqEventBufferCount = 0;
|
||||
critical_section_exit(&critSec);
|
||||
}
|
||||
|
||||
response[2] = eventBufferCountCopy;
|
||||
memcpy(&(response[3]), eventBufferCopy, sizeof(uint8_t) * eventBufferCountCopy);
|
||||
eventBufferCountCopy = 0;
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
|
||||
28
firmware/source/interfaces/Gpio.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef _INTERFACE_GPIO_H
|
||||
#define _INTERFACE_GPIO_H
|
||||
|
||||
#include "PicoInterfacesBoard.h"
|
||||
#include "BaseInterface.h"
|
||||
#include "pico/sync.h"
|
||||
|
||||
class Gpio : public BaseInterface {
|
||||
public:
|
||||
Gpio();
|
||||
virtual ~Gpio();
|
||||
|
||||
CmdStatus process(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus task(uint8_t response[64]);
|
||||
|
||||
protected:
|
||||
CmdStatus initPin(uint8_t const *cmd);
|
||||
CmdStatus setPin(uint8_t const *cmd);
|
||||
CmdStatus getPin(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus setIrq(uint8_t const *cmd);
|
||||
CmdStatus getIrq(uint8_t const *cmd, uint8_t response[64]);
|
||||
private:
|
||||
repeating_timer_t _debounceTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
165
firmware/source/interfaces/I2cMaster.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#include "I2cMaster.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
I2CMaster::I2CMaster(uint8_t i2cIndex, uint streamBufferSize = 512)
|
||||
: StreamedInterface(streamBufferSize),
|
||||
_i2cInst(i2cIndex == 0 ? i2c0 : i2c1),
|
||||
_sdaGP(i2cIndex == 0 ? Pin::ID::GP4_I2C0_SDA : Pin::ID::GP14_I2C1_SDA),
|
||||
_sclGP(i2cIndex == 0 ? Pin::ID::GP5_I2C0_SCL : Pin::ID::GP15_I2C1_SCL),
|
||||
_currentStreamAddress(0) {
|
||||
|
||||
}
|
||||
|
||||
I2CMaster::~I2CMaster() {
|
||||
|
||||
}
|
||||
|
||||
uint8_t I2CMaster::getInstIndex() {
|
||||
return static_cast<uint8_t>(i2c_hw_index(_i2cInst));
|
||||
}
|
||||
|
||||
CmdStatus I2CMaster::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
const uint i2cIndex = getInstIndex();
|
||||
|
||||
if(cmd[0] == (Report::ID::I2C0_INIT + i2cIndex * 0x10)) {
|
||||
status = init(cmd);
|
||||
} else if(cmd[0] == (Report::ID::I2C0_DEINIT + i2cIndex * 0x10) ) {
|
||||
status = deInit();
|
||||
} else if(cmd[0] == (Report::ID::I2C0_WRITE + i2cIndex * 0x10)) {
|
||||
status = write(cmd);
|
||||
} else if(cmd[0] == (Report::ID::I2C0_READ + i2cIndex * 0x10)) {
|
||||
status = read(cmd, response);
|
||||
} else if(cmd[0] == (Report::ID::I2C0_WRITE_FROM_UART + i2cIndex * 0x10)) {
|
||||
status = writeFromUart(cmd);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus I2CMaster::task(uint8_t response[64]) {
|
||||
if(_totalRemainingBytesToSend == 0)
|
||||
return CmdStatus::NOT_CONCERNED;
|
||||
|
||||
bool error = false;
|
||||
while(_totalRemainingBytesToSend > 0 && streamRxAvailableSize() && !error){
|
||||
streamRxRead();
|
||||
uint nbBytes = std::min(_totalRemainingBytesToSend, _bufferRx.size());
|
||||
bool noStop = (_totalRemainingBytesToSend - nbBytes) > 0;
|
||||
|
||||
int nbWritten = i2c_write_blocking(
|
||||
_i2cInst,
|
||||
_currentStreamAddress, // addr
|
||||
_bufferRx.getDataPtr(), //src
|
||||
nbBytes, //len
|
||||
noStop
|
||||
);
|
||||
_i2cInst->restart_on_next = 0;
|
||||
|
||||
if(nbWritten != nbBytes) {
|
||||
error = true;
|
||||
} else {
|
||||
_totalRemainingBytesToSend -= static_cast<uint>(nbWritten);
|
||||
}
|
||||
_bufferRx.setSize(0);
|
||||
|
||||
break; // break ou pas ? est ce qu'on essaye de tout envoyer sans redonner la main a l'event loop ou on fait le contraire ?
|
||||
}
|
||||
|
||||
if(error || _totalRemainingBytesToSend == 0) {
|
||||
_totalRemainingBytesToSend = 0;
|
||||
_currentStreamAddress = 0;
|
||||
response[0] = Report::ID::I2C0_WRITE_FROM_UART + (getInstIndex() * 0x10);
|
||||
//memset(&response[2], 0, 62);
|
||||
_i2cInst->restart_on_next = 1;
|
||||
return error ? CmdStatus::NOK : CmdStatus::OK;
|
||||
}
|
||||
return CmdStatus::NOT_FINISHED;
|
||||
}
|
||||
|
||||
CmdStatus I2CMaster::init(uint8_t const *cmd) {
|
||||
uint32_t baudrate = convertBytesToUInt32(&cmd[2]);
|
||||
//printf("i2c baudrate %d kbaud %d %d %d\n", baudrate, report[2], report[3], sizeof(int));
|
||||
i2c_init(_i2cInst, baudrate);
|
||||
gpio_set_function(_sdaGP, GPIO_FUNC_I2C);
|
||||
gpio_set_function(_sclGP, GPIO_FUNC_I2C);
|
||||
if(cmd[1]) {
|
||||
gpio_pull_up(_sdaGP);
|
||||
gpio_pull_up(_sclGP);
|
||||
}
|
||||
setInterfaceState(InterfaceState::INTIALIZED);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus I2CMaster::deInit() {
|
||||
i2c_deinit(_i2cInst);
|
||||
gpio_disable_pulls(_sdaGP);
|
||||
gpio_disable_pulls(_sclGP);
|
||||
setInterfaceState(InterfaceState::NOT_INITIALIZED);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CmdStatus I2CMaster::write(const uint8_t *cmd){
|
||||
uint nbytes = convertBytesToUInt32(&cmd[3]);
|
||||
//printf("i2c write addr=%d size=%d => ", report[1], nbytes);
|
||||
|
||||
bool noStop = cmd[2] == 0x01 ? false : true;
|
||||
bool over = false;
|
||||
if(nbytes > (HID_CMD_SIZE - 7)) {
|
||||
noStop = true;
|
||||
nbytes = HID_CMD_SIZE - 7;
|
||||
over = true;
|
||||
}
|
||||
|
||||
/*for(int it = 0; it < nbytes; it++)
|
||||
{
|
||||
printf("0x%02x ", report[4 + it]);
|
||||
}*/
|
||||
|
||||
int nbWritten = i2c_write_blocking(
|
||||
_i2cInst,
|
||||
cmd[1], // addr
|
||||
cmd + 7, //src
|
||||
nbytes, //len
|
||||
noStop
|
||||
);
|
||||
//printf("i2c write res=%d\n", nbWritten);
|
||||
if(nbWritten == PICO_ERROR_GENERIC || nbWritten != static_cast<int>(nbytes))
|
||||
return CmdStatus::NOK;
|
||||
if(over)
|
||||
_i2cInst->restart_on_next = 0;
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus I2CMaster::read(const uint8_t *report, uint8_t *ret){
|
||||
//printf("i2c read addr=%d size=%d\n", report[1], report[3]);
|
||||
int nbRead = i2c_read_blocking(
|
||||
_i2cInst,
|
||||
report[1], // addr
|
||||
ret + 2, //dst
|
||||
report[3], //len
|
||||
report[2] == 0x01 ? false : true
|
||||
);
|
||||
/*printf("i2c read res=%d", nbRead);
|
||||
if(nbRead > 0) {
|
||||
printf(" => ");
|
||||
for(int it = 0; it < nbRead; it++)
|
||||
{
|
||||
printf("0x%02x ", ret[2+it]);
|
||||
}
|
||||
}
|
||||
printf("\n");*/
|
||||
if(nbRead == PICO_ERROR_GENERIC || nbRead != report[3])
|
||||
return CmdStatus::NOK;
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus I2CMaster::writeFromUart(const uint8_t *cmd){
|
||||
flushStreamRx();
|
||||
_totalRemainingBytesToSend = convertBytesToUInt32(&cmd[2]);
|
||||
_currentStreamAddress = cmd[1];
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
33
firmware/source/interfaces/I2cMaster.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _INTERFACE_I2C_MASTER_H
|
||||
#define _INTERFACE_I2C_MASTER_H
|
||||
|
||||
#include "PicoInterfacesBoard.h"
|
||||
#include "StreamedInterface.h"
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
|
||||
class I2CMaster : public StreamedInterface {
|
||||
public:
|
||||
I2CMaster(uint8_t i2cIndex, uint streamBufferSize);
|
||||
virtual ~I2CMaster();
|
||||
|
||||
CmdStatus process(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus task(uint8_t response[64]);
|
||||
|
||||
protected:
|
||||
CmdStatus init(uint8_t const *cmd);
|
||||
CmdStatus deInit();
|
||||
CmdStatus write(const uint8_t *cmd);
|
||||
CmdStatus writeFromUart(const uint8_t *cmd);
|
||||
CmdStatus read(const uint8_t *cmd, uint8_t *ret);
|
||||
uint8_t getInstIndex();
|
||||
|
||||
i2c_inst_t *_i2cInst;
|
||||
uint _sdaGP;
|
||||
uint _sclGP;
|
||||
uint8_t _currentStreamAddress;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
1
firmware/source/interfaces/PicoInterfacesBoard.cpp
Normal file
|
|
@ -0,0 +1 @@
|
|||
#include "PicoInterfacesBoard.h"
|
||||
172
firmware/source/interfaces/PicoInterfacesBoard.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#ifndef _PICO_INTERFACES_BOARD_H
|
||||
#define _PICO_INTERFACES_BOARD_H
|
||||
|
||||
#define HID_CMD_SIZE 64
|
||||
#define HID_RESPONSE_SIZE 64
|
||||
|
||||
// TODO: PWM
|
||||
// GP pin
|
||||
namespace Pin {
|
||||
enum ID {
|
||||
// GPIO
|
||||
// Mode
|
||||
GP2_MODE = 2,
|
||||
// SW
|
||||
GP_6 = 6,
|
||||
GP_9 = 9,
|
||||
// Led
|
||||
GP_3 = 3,
|
||||
// Other
|
||||
GP_7 = 7,
|
||||
GP_8 = 8,
|
||||
GP_21 = 21,
|
||||
GP_22 = 22,
|
||||
GP_28 = 28,
|
||||
|
||||
// Analog
|
||||
GP26_ADC0 = 26,
|
||||
GP27_ADC1 = 27,
|
||||
|
||||
// UART0
|
||||
GP0_UART0_TX = 0,
|
||||
GP1_UART0_RX = 1,
|
||||
|
||||
// SPI0
|
||||
GP18_SPI0_CK = 18,
|
||||
GP19_SPI0_MOSI = 19,
|
||||
GP16_SPI0_MISO = 16,
|
||||
GP17_SPI0_CS1 = 17,
|
||||
GP20_SPI0_CS2 = 20,
|
||||
|
||||
// SPI1
|
||||
GP10_SPI1_CK = 10,
|
||||
GP11_SPI1_MOSI = 11,
|
||||
GP12_SPI1_MISO = 12,
|
||||
GP13_SPI1_CS1 = 13,
|
||||
|
||||
// I2C0
|
||||
GP4_I2C0_SDA = 4,
|
||||
GP5_I2C0_SCL = 5,
|
||||
|
||||
// I2C1
|
||||
GP14_I2C1_SDA = 14,
|
||||
GP15_I2C1_SCL = 15
|
||||
};
|
||||
}
|
||||
|
||||
enum CmdStatus {
|
||||
OK = 0x01,
|
||||
NOK = 0x02,
|
||||
NOT_FINISHED = 0xFE, // INTERNAL
|
||||
NOT_CONCERNED = 0xFF
|
||||
};
|
||||
|
||||
enum IRQ_EVENT {
|
||||
EVENT_NONE = 0x00,
|
||||
EVENT_RISING = 0x01,
|
||||
EVENT_FALLING = 0x02,
|
||||
};
|
||||
|
||||
// Each report size is is 64 bytes.
|
||||
// In general reports return | Report::ID | CmdStatus::OK or CmdStatus::NOK |
|
||||
namespace Report {
|
||||
enum ID {
|
||||
// SYSTEM
|
||||
// | RESET | => | RESET | CmdStatus::OK | then system reset
|
||||
SYS_RESET = 0x10,
|
||||
// | SYS_GET_SN | => | SYS_GET_SN | CmdStatus::OK | SN * 8 bytes |
|
||||
SYS_GET_SN = 0x11,
|
||||
// | SYS_GET_VN | => | SYS_GET_VN | CmdStatus::OK | MAJOR VERSION | MINOR VERSION | PATCH VERSION |
|
||||
SYS_GET_VN = 0x12,
|
||||
|
||||
// GPIO
|
||||
// | GPIO_INIT_PIN | GP NUMBER | DIRECTION (0=INPUT; 1=OUTPUT) | PULL (0=NONE; 1=PULLUP; 2=PULLDOWN)
|
||||
GPIO_INIT_PIN = 0x20,
|
||||
// | GPIO_SET_VALUE | GP NUMBER | VALUE (0=LOW; 1=HIGH) |
|
||||
GPIO_SET_VALUE = 0x21,
|
||||
// | GPIO_GET_VALUE | GP NUMBER | => | GPIO_GET_VALUE | CmdStatus::OK | GP NUMBER | VALUE (0=LOW; 1=HIGH) |
|
||||
GPIO_GET_VALUE = 0x22,
|
||||
// | GPIO_SET_IRQ | GP NUMBER | EVENT (EVENT_NONE or (EVENT_RISING | EVENT_FALLING)) | DEBOUNCED (0:False; 1:True)
|
||||
GPIO_SET_IRQ = 0x23,
|
||||
// | GPIO_GET_IRQ | => | GPIO_GET_IRQ | CmdStatus::OK | IRQ_NUMBER | IRQ(GP NUMBER[0..5] | EVENT (EVENT_RISING | EVENT_FALLING) [6..7]) * IRQ_NUMBER|
|
||||
GPIO_GET_IRQ = 0x24,
|
||||
|
||||
// PWM
|
||||
// | PWM_INIT_PIN | GP NUMBER | => | PWM_INIT_PIN | CmdStatus::OK|NOK | GP NUMBER | SLICE NUMBER | CHANNEL | err : 0x01: Already used slice
|
||||
PWM_INIT_PIN = 0x30,
|
||||
// | PWM_DEINIT_PIN | GP NUMBER |
|
||||
PWM_DEINIT_PIN = 0x31,
|
||||
// | PWM_SET_FREQ | GP NUMBER | FREQ[4] L.Endian | => | PWM_SET_FREQ | CmdStatus::OK|NOK | GP NUMBER | err: 0x01 : Different freq on same slice; 0x02: Freq too low; 0x03:Fre too high|
|
||||
PWM_SET_FREQ = 0x32,
|
||||
// | PWM_GET_FREQ |GP NUMBER | => | PWM_GET_FREQ | CmdStatus::OK | GP NUMBER | FREQ[4] L.Endian |
|
||||
PWM_GET_FREQ = 0x33,
|
||||
// | PWM_SET_DUTY_U16 | GP NUMBER | DUTY | DUTY >> 8 | => | PWM_SET_DUTY_U16 | CmdStatus::OK|NOK |
|
||||
PWM_SET_DUTY_U16 = 0x34,
|
||||
// | PWM_GET_DUTY_U16 | GP NUMBER => | PWM_GET_DUTY_U16 | CmdStatus::OK|NOK | GP NUMBER | DUTY | DUTY >> 8 |
|
||||
PWM_GET_DUTY_U16 = 0x35,
|
||||
// | PWM_SET_DUTY_NS | GP NUMBER | DUTY[4] L.Endian | => | PWM_SET_DUTY_NS | CmdStatus::OK|NOK | GP NUMBER | err: 0x01 = Too large duty |
|
||||
PWM_SET_DUTY_NS = 0x36,
|
||||
// | PWM_GET_DUTY_NS | GP NUMBER | => | PWM_GET_DUTY_NS | CmdStatus::OK|NOK | GP NUMBER | DUTY[4] L.Endian |
|
||||
PWM_GET_DUTY_NS = 0x37,
|
||||
|
||||
// ADC
|
||||
// | ADC_INIT_PIN | GP NUMBER |
|
||||
ADC_INIT_PIN = 0x40,
|
||||
// | ADC_GET_VALUE | GP NUMBER | => | ADC_GET_VALUE | CmdStatus::OK|NOK | GP NUMBER | VALUE[2] L.Endian (12bits=4096) |
|
||||
ADC_GET_VALUE = 0x41,
|
||||
|
||||
// UART
|
||||
// | UART0_INIT | MODE (NOT USED) | BAUDRATE[4] L.Endian |
|
||||
UART0_INIT = 0x50,
|
||||
// | UART0_DEINIT |
|
||||
UART0_DEINIT = 0x51,
|
||||
// | UART0_WRITE | NB_BYTES[1] | PAYLOAD |=> First | UART_WRITE | CmdStatus::OK |
|
||||
UART0_WRITE = 0x52,
|
||||
// | UART0_READ | => First | UART_READ_FROM_UART | CmdStatus::OK | NB_BYTES[1] | PAYLOAD |
|
||||
UART0_READ = 0x53,
|
||||
|
||||
// SPI0
|
||||
// | SPI0_INIT | MODE (To implement) | BAUDRATE[4] L.Endian |
|
||||
SPI0_INIT = 0x60,
|
||||
// | SPI0_DEINIT |
|
||||
SPI0_DEINIT = 0x61,
|
||||
// | SPI0_WRITE | NB_BYTES[1] | PAYLOAD |
|
||||
SPI0_WRITE = 0x62,
|
||||
// | I2C0_READ | WRITE_BYTE | NB_BYTES[1] | => | SPI0_READ | CmdStatus::OK | PAYLOAD |
|
||||
SPI0_READ = 0x63,
|
||||
// | SPI0_WRITE_FROM_UART | NB_BYTES[4] L.Endian | => First | SPI0_WRITE_FROM_UART | CmdStatus::OK | and after the CDC stream | SPI0_WRITE_FROM_UART | CmdStatus::OK |
|
||||
SPI0_WRITE_FROM_UART = 0x64,
|
||||
|
||||
// SPI1
|
||||
SPI1_INIT = SPI0_INIT + 0x10,
|
||||
SPI1_DEINIT = SPI0_DEINIT + 0x10,
|
||||
SPI1_WRITE = SPI0_WRITE + 0x10,
|
||||
SPI1_READ = SPI0_READ + 0x10,
|
||||
SPI1_WRITE_FROM_UART = SPI0_WRITE_FROM_UART + 0x10,
|
||||
|
||||
// I2C0
|
||||
// | I2C0_INIT | PULLUP(1=True) | BAUDRATE[4] L.Endian |
|
||||
I2C0_INIT = 0x80,
|
||||
// | I2C0_DEINIT |
|
||||
I2C0_DEINIT = 0x81,
|
||||
// | I2C0_WRITE | ADDR | SEND_STOP | NB_BYTES[4] L.Endian | PAYLOAD |
|
||||
I2C0_WRITE = 0x82,
|
||||
// | I2C0_READ | ADDR | SEND_STOP | NB_BYTES => | I2C0_READ | CmdStatus::OK | PAYLOAD |
|
||||
I2C0_READ = 0x83,
|
||||
// | I2C0_WRITE_FROM_UART | ADDR | NB_BYTES[4] L.Endian | => First | I2C0_WRITE_FROM_UART | CmdStatus::OK | and after the CDC stream | I2C0_WRITE_FROM_UART | CmdStatus::OK |
|
||||
I2C0_WRITE_FROM_UART = 0x84,
|
||||
|
||||
// I2C1
|
||||
I2C1_INIT = I2C0_INIT + 0x10,
|
||||
I2C1_DEINIT = I2C0_DEINIT + 0x10,
|
||||
I2C1_WRITE = I2C0_WRITE + 0x10,
|
||||
I2C1_READ = I2C0_READ + 0x10,
|
||||
I2C1_WRITE_FROM_UART = I2C0_WRITE_FROM_UART + 0x10,
|
||||
|
||||
// TODO: WS2812B LED
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
224
firmware/source/interfaces/Pwm.cpp
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Use code of MicroPython (https://github.com/micropython/micropython/blob/master/ports/rp2/machine_pwm.c)
|
||||
* See License file
|
||||
*/
|
||||
|
||||
#include "Pwm.h"
|
||||
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
Pwm::Pwm() {
|
||||
setInterfaceState(InterfaceState::INTIALIZED);
|
||||
}
|
||||
|
||||
Pwm::~Pwm() {
|
||||
|
||||
}
|
||||
|
||||
CmdStatus Pwm::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
|
||||
if(cmd[0] == Report::ID::PWM_INIT_PIN) {
|
||||
status = initPwm(cmd, response);
|
||||
} else if(cmd[0] == Report::ID::PWM_DEINIT_PIN) {
|
||||
status = deInitPwm(cmd);
|
||||
} else if (cmd[0] == Report::ID::PWM_SET_FREQ) {
|
||||
status = setFreq(cmd, response);
|
||||
} else if (cmd[0] == Report::ID::PWM_GET_FREQ) {
|
||||
status = getFreq(cmd, response);
|
||||
} else if (cmd[0] == Report::ID::PWM_SET_DUTY_U16) {
|
||||
status = setDutyU16(cmd);
|
||||
} else if (cmd[0] == Report::ID::PWM_GET_DUTY_U16) {
|
||||
status = getDutyU16(cmd, response);
|
||||
} else if (cmd[0] == Report::ID::PWM_SET_DUTY_NS) {
|
||||
status = setDutyNs(cmd, response);
|
||||
} else if (cmd[0] == Report::ID::PWM_GET_DUTY_NS) {
|
||||
status = getDutyNs(cmd, response);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::task(uint8_t response[64]) {
|
||||
(void)response;
|
||||
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::initPwm(uint8_t const *cmd, uint8_t response[64]) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
response[2] = static_cast<uint8_t>(gpio);
|
||||
response[3] = static_cast<uint8_t>(sliceNb);
|
||||
response[4] = static_cast<uint8_t>(channel);
|
||||
|
||||
Slice &slice = _sliceArray[sliceNb];
|
||||
if(slice.isGpioChannelUsed(channel)) {
|
||||
response[5] = 0x01;
|
||||
return CmdStatus::NOK;
|
||||
}
|
||||
|
||||
gpio_set_function(gpio, GPIO_FUNC_PWM);
|
||||
slice.setGpioChannel(channel, gpio);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::deInitPwm(uint8_t const *cmd) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
Slice &slice = _sliceArray[sliceNb];
|
||||
if(slice.isGpioChannelUsed(channel)) {
|
||||
slice.unsetGpioChannel(channel);
|
||||
}
|
||||
|
||||
if(slice.isFree()) {
|
||||
pwm_set_enabled(sliceNb, false);
|
||||
}
|
||||
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::setFreq(uint8_t const *cmd, uint8_t response[64]) {
|
||||
bool error = false;
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
//uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
response[2] = gpio;
|
||||
response[3] = 0x00;
|
||||
Slice &slice = _sliceArray[sliceNb];
|
||||
const uint32_t source_hz = clock_get_hz(clk_sys);
|
||||
|
||||
// Set the frequency, making "top" as large as possible for maximum resolution.
|
||||
// Maximum "top" is set at 65534 to be able to achieve 100% duty with 65535.
|
||||
const uint32_t TOP_MAX = 65534;
|
||||
uint32_t freq = convertBytesToUInt32(&cmd[2]);
|
||||
uint32_t div16_top = 16 * source_hz / freq;
|
||||
uint32_t top = 1;
|
||||
for (;;) {
|
||||
// Try a few small prime factors to get close to the desired frequency.
|
||||
if (div16_top >= 16 * 5 && div16_top % 5 == 0 && top * 5 <= TOP_MAX) {
|
||||
div16_top /= 5;
|
||||
top *= 5;
|
||||
} else if (div16_top >= 16 * 3 && div16_top % 3 == 0 && top * 3 <= TOP_MAX) {
|
||||
div16_top /= 3;
|
||||
top *= 3;
|
||||
} else if (div16_top >= 16 * 2 && top * 2 <= TOP_MAX) {
|
||||
div16_top /= 2;
|
||||
top *= 2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (div16_top < 16) {
|
||||
response[3] = 0x03;
|
||||
error = true;
|
||||
} else if (div16_top >= 256 * 16) {
|
||||
response[3] = 0x02;
|
||||
error = true;
|
||||
}
|
||||
|
||||
if(!error && slice.isFreqComputed && ( pwm_hw->slice[sliceNb].div != div16_top || pwm_hw->slice[sliceNb].top != top )) {
|
||||
response[3] = 0x01;
|
||||
error = true;
|
||||
}
|
||||
|
||||
if(!error){
|
||||
slice.isFreqComputed = true;
|
||||
pwm_hw->slice[sliceNb].div = div16_top;
|
||||
pwm_hw->slice[sliceNb].top = top;
|
||||
return CmdStatus::OK;
|
||||
} else {
|
||||
return CmdStatus::NOK;
|
||||
}
|
||||
}
|
||||
|
||||
CmdStatus Pwm::getFreq(uint8_t const *cmd, uint8_t response[64]){
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint slice = pwm_gpio_to_slice_num(gpio);
|
||||
const uint32_t source_hz = clock_get_hz(clk_sys);
|
||||
const uint32_t div16 = pwm_hw->slice[slice].div;
|
||||
const uint32_t top = pwm_hw->slice[slice].top;
|
||||
const uint32_t pwm_freq = 16 * source_hz / div16 / top;
|
||||
|
||||
response[2] = gpio;
|
||||
convertUInt32ToBytes(pwm_freq, &response[3]);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::setDutyU16(uint8_t const *cmd) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
uint16_t duty_u16 = convertBytesToUInt16(&cmd[2]);
|
||||
const uint32_t top = pwm_hw->slice[sliceNb].top;
|
||||
uint32_t cc = duty_u16 * (top + 1) / 65535;
|
||||
pwm_set_chan_level(sliceNb, channel, cc);
|
||||
pwm_set_enabled(sliceNb, true);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::getDutyU16(uint8_t const *cmd, uint8_t response[64]) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
const uint32_t top = pwm_hw->slice[sliceNb].top;
|
||||
uint32_t cc = pwm_hw->slice[sliceNb].cc;
|
||||
cc = (cc >> (channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
|
||||
uint32_t duty_u16 = cc * 65535 / (top + 1);
|
||||
|
||||
response[2] = gpio;
|
||||
convertUInt16ToBytes(static_cast<uint16_t>(duty_u16), &response[3]);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus Pwm::setDutyNs(uint8_t const *cmd, uint8_t response[64]) {
|
||||
bool error = false;
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
uint32_t source_hz = clock_get_hz(clk_sys);
|
||||
uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[sliceNb].div;
|
||||
|
||||
uint32_t duty_ns = convertBytesToUInt32(&cmd[2]);
|
||||
|
||||
uint32_t cc = (uint64_t)duty_ns * slice_hz / 1000000000ULL;
|
||||
if (cc > 65535) {
|
||||
error = true;
|
||||
response[3] = 0x01;
|
||||
}
|
||||
response[2] = gpio;
|
||||
if(!error) {
|
||||
pwm_set_chan_level(sliceNb, channel, cc);
|
||||
pwm_set_enabled(sliceNb, true);
|
||||
return CmdStatus::OK;
|
||||
} else {
|
||||
return CmdStatus::NOK;
|
||||
}
|
||||
}
|
||||
|
||||
CmdStatus Pwm::getDutyNs(uint8_t const *cmd, uint8_t response[64]) {
|
||||
const uint8_t gpio = cmd[1];
|
||||
uint sliceNb = pwm_gpio_to_slice_num(gpio);
|
||||
uint channel = pwm_gpio_to_channel(gpio);
|
||||
|
||||
uint32_t source_hz = clock_get_hz(clk_sys);
|
||||
uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[sliceNb].div;
|
||||
|
||||
uint32_t cc = pwm_hw->slice[sliceNb].cc;
|
||||
cc = (cc >> (channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
|
||||
uint64_t dutyNs = static_cast<uint64_t>(cc) * 1000000000ULL / slice_hz;
|
||||
|
||||
response[2] = gpio;
|
||||
convertUInt32ToBytes(static_cast<uint32_t>(dutyNs), &response[3]);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
63
firmware/source/interfaces/Pwm.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef _INTERFACE_PWM_H
|
||||
#define _INTERFACE_PWM_H
|
||||
|
||||
#include "PicoInterfacesBoard.h"
|
||||
#include "BaseInterface.h"
|
||||
|
||||
struct Slice {
|
||||
int gpioChannelA = -1;
|
||||
int gpioChannelB = -1;
|
||||
bool isFreqComputed = false;
|
||||
|
||||
inline bool isFree() {return (gpioChannelA == -1 && gpioChannelB == -1);}
|
||||
|
||||
inline bool isGpioChannelUsed(uint channel) {
|
||||
if(channel == 0)
|
||||
return gpioChannelA >= 0;
|
||||
else
|
||||
return gpioChannelB >= 0;
|
||||
}
|
||||
|
||||
inline bool setGpioChannel(uint channel, uint gpio) {
|
||||
if(channel == 0)
|
||||
return gpioChannelA = gpio;
|
||||
else
|
||||
return gpioChannelB = gpio;
|
||||
}
|
||||
|
||||
inline bool unsetGpioChannel(uint channel) {
|
||||
if(channel == 0)
|
||||
gpioChannelA = -1;
|
||||
else
|
||||
gpioChannelB = -1;
|
||||
|
||||
if (isFree()) {
|
||||
isFreqComputed = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Pwm : public BaseInterface {
|
||||
public:
|
||||
Pwm();
|
||||
virtual ~Pwm();
|
||||
|
||||
CmdStatus process(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus task(uint8_t response[64]);
|
||||
|
||||
protected:
|
||||
CmdStatus initPwm(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus deInitPwm(uint8_t const *cmd);
|
||||
CmdStatus setFreq(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus getFreq(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus setDutyU16(uint8_t const *cmd);
|
||||
CmdStatus getDutyU16(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus setDutyNs(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus getDutyNs(uint8_t const *cmd, uint8_t response[64]);
|
||||
|
||||
Slice _sliceArray[8];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
115
firmware/source/interfaces/SpiMaster.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#include "SpiMaster.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
SPIMaster::SPIMaster(uint8_t spiIndex, uint streamBufferSize = 512)
|
||||
: StreamedInterface(streamBufferSize),
|
||||
_spiInst(spiIndex == 0 ? spi0 : spi1),
|
||||
_clkGP(spiIndex == 0 ? Pin::ID::GP18_SPI0_CK : Pin::ID::GP10_SPI1_CK),
|
||||
_mosiGP(spiIndex == 0 ? Pin::ID::GP19_SPI0_MOSI : Pin::ID::GP11_SPI1_MOSI),
|
||||
_misoGP(spiIndex == 0 ? Pin::ID::GP16_SPI0_MISO : Pin::ID::GP12_SPI1_MISO){
|
||||
|
||||
}
|
||||
|
||||
SPIMaster::~SPIMaster() {
|
||||
|
||||
}
|
||||
|
||||
uint8_t SPIMaster::getInstIndex() {
|
||||
//return static_cast<uint8_t>(spi_hw_index(_spiInst));
|
||||
return _spiInst == spi1 ? 1 : 0;
|
||||
}
|
||||
|
||||
CmdStatus SPIMaster::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
const uint spiIndex = getInstIndex();
|
||||
|
||||
if(cmd[0] == (Report::ID::SPI0_INIT + spiIndex * 0x10)) {
|
||||
status = init(cmd);
|
||||
} else if(cmd[0] == (Report::ID::SPI0_DEINIT + spiIndex * 0x10) ) {
|
||||
status = deInit();
|
||||
} else if(cmd[0] == (Report::ID::SPI0_WRITE + spiIndex * 0x10)) {
|
||||
status = write(cmd);
|
||||
} else if(cmd[0] == (Report::ID::SPI0_READ + spiIndex * 0x10)) {
|
||||
status = read(cmd, response);
|
||||
} else if(cmd[0] == (Report::ID::SPI0_WRITE_FROM_UART + spiIndex * 0x10)) {
|
||||
status = writeFromUart(cmd);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus SPIMaster::task(uint8_t response[64]) {
|
||||
if(_totalRemainingBytesToSend == 0)
|
||||
return CmdStatus::NOT_CONCERNED;
|
||||
|
||||
bool error = false;
|
||||
while(_totalRemainingBytesToSend > 0 && streamRxAvailableSize() && !error){
|
||||
streamRxRead();
|
||||
uint nbBytes = std::min(_totalRemainingBytesToSend, _bufferRx.size());
|
||||
int nbWritten = spi_write_blocking (_spiInst, _bufferRx.getDataPtr(), nbBytes);
|
||||
if(nbWritten != static_cast<int>(nbBytes)) {
|
||||
error = true;
|
||||
} else {
|
||||
_totalRemainingBytesToSend -= static_cast<uint>(nbWritten);
|
||||
}
|
||||
_bufferRx.setSize(0);
|
||||
//printf("->Total = %d\n", _totalRemainingBytesToSend);
|
||||
|
||||
break; // break ou pas ? est ce qu'on essaye de tout envoyer sans redonner la main a l'event loop ou on fait le contraire ?
|
||||
}
|
||||
|
||||
if(error || _totalRemainingBytesToSend == 0) {
|
||||
_totalRemainingBytesToSend = 0;
|
||||
//printf("->END = %d\n", _totalRemainingBytesToSend);
|
||||
response[0] = Report::ID::SPI0_WRITE_FROM_UART + (getInstIndex() * 0x10);
|
||||
return error ? CmdStatus::NOK : CmdStatus::OK;
|
||||
}
|
||||
return CmdStatus::NOT_FINISHED;
|
||||
}
|
||||
|
||||
CmdStatus SPIMaster::init(uint8_t const *cmd) {
|
||||
uint32_t mode = cmd[1];
|
||||
uint32_t baudrate = convertBytesToUInt32(&cmd[2]);
|
||||
|
||||
spi_init(_spiInst, baudrate);
|
||||
gpio_set_function(_clkGP, GPIO_FUNC_SPI);
|
||||
gpio_set_function(_mosiGP, GPIO_FUNC_SPI);
|
||||
gpio_set_function(_misoGP, GPIO_FUNC_SPI);
|
||||
|
||||
setInterfaceState(InterfaceState::INTIALIZED);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus SPIMaster::deInit() {
|
||||
spi_deinit(_spiInst);
|
||||
setInterfaceState(InterfaceState::NOT_INITIALIZED);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CmdStatus SPIMaster::write(const uint8_t *cmd){
|
||||
const uint nbytes = cmd[1];
|
||||
int nbWritten = spi_write_blocking (_spiInst, cmd + 2, nbytes);
|
||||
if(nbWritten == PICO_ERROR_GENERIC || nbWritten != static_cast<int>(nbytes))
|
||||
return CmdStatus::NOK;
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus SPIMaster::read(const uint8_t *cmd, uint8_t *ret){
|
||||
const uint8_t writeByte = cmd[1];
|
||||
const uint nbytes = cmd[2];
|
||||
int nbRead = spi_read_blocking (_spiInst, writeByte, ret + 2, nbytes);
|
||||
if(nbRead == PICO_ERROR_GENERIC || nbRead != nbytes)
|
||||
return CmdStatus::NOK;
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
CmdStatus SPIMaster::writeFromUart(const uint8_t *cmd){
|
||||
flushStreamRx();
|
||||
_totalRemainingBytesToSend = convertBytesToUInt32(&cmd[1]);
|
||||
//printf("Total = %d", _totalRemainingBytesToSend);
|
||||
return CmdStatus::OK;
|
||||
}
|
||||
|
||||
32
firmware/source/interfaces/SpiMaster.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef _INTERFACE_SPI_MASTER_H
|
||||
#define _INTERFACE_SPI_MASTER_H
|
||||
|
||||
#include "PicoInterfacesBoard.h"
|
||||
#include "StreamedInterface.h"
|
||||
#include "hardware/spi.h"
|
||||
|
||||
|
||||
class SPIMaster : public StreamedInterface {
|
||||
public:
|
||||
SPIMaster(uint8_t i2cIndex, uint streamBufferSize);
|
||||
virtual ~SPIMaster();
|
||||
|
||||
CmdStatus process(uint8_t const *cmd, uint8_t response[64]);
|
||||
CmdStatus task(uint8_t response[64]);
|
||||
|
||||
protected:
|
||||
CmdStatus init(uint8_t const *cmd);
|
||||
CmdStatus deInit();
|
||||
CmdStatus write(const uint8_t *cmd);
|
||||
CmdStatus writeFromUart(const uint8_t *cmd);
|
||||
CmdStatus read(const uint8_t *cmd, uint8_t *ret);
|
||||
uint8_t getInstIndex();
|
||||
|
||||
spi_inst_t *_spiInst;
|
||||
uint _clkGP;
|
||||
uint _mosiGP;
|
||||
uint _misoGP;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
12
firmware/source/interfaces/StreamBuffer.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "StreamBuffer.h"
|
||||
|
||||
|
||||
|
||||
StreamBuffer::StreamBuffer(uint streamBufferSize)
|
||||
: _buffer(streamBufferSize, 0), _bufSize(0) {
|
||||
|
||||
}
|
||||
|
||||
StreamBuffer::~StreamBuffer() {
|
||||
|
||||
}
|
||||
23
firmware/source/interfaces/StreamBuffer.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef _INTERFACE_STREAM_BUFFER_H
|
||||
#define _INTERFACE_STREAM_BUFFER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class StreamBuffer {
|
||||
public:
|
||||
StreamBuffer(uint streamBufferSize);
|
||||
virtual ~StreamBuffer();
|
||||
inline uint32_t getAllocateSize() const {return static_cast<uint32_t>(_buffer.size());}
|
||||
inline uint8_t* getDataPtr() {return static_cast<uint8_t*>(_buffer.data());}
|
||||
inline uint32_t setSize(uint32_t size) {_bufSize = size;}
|
||||
inline uint32_t size() const {return _bufSize;}
|
||||
protected:
|
||||
std::vector<uint8_t> _buffer;
|
||||
uint _bufSize;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
26
firmware/source/interfaces/StreamedInterface.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "StreamedInterface.h"
|
||||
//#include <algorithm>
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
StreamedInterface::StreamedInterface(uint streamBufferSize)
|
||||
: _bufferRx(streamBufferSize), _totalRemainingBytesToSend(0){
|
||||
|
||||
}
|
||||
|
||||
StreamedInterface::~StreamedInterface() {
|
||||
|
||||
}
|
||||
|
||||
void StreamedInterface::flushStreamRx() {
|
||||
tud_cdc_read_flush();
|
||||
}
|
||||
|
||||
uint32_t StreamedInterface::streamRxAvailableSize() {
|
||||
return tud_cdc_available();
|
||||
}
|
||||
|
||||
uint32_t StreamedInterface::streamRxRead() {
|
||||
_bufferRx.setSize(tud_cdc_read(_bufferRx.getDataPtr(), std::min(_bufferRx.getAllocateSize(), streamRxAvailableSize())));
|
||||
return _bufferRx.size();
|
||||
}
|
||||
24
firmware/source/interfaces/StreamedInterface.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _STREAMED_INTERFACES_PICO_H
|
||||
#define _STREAMED_INTERFACES_PICO_H
|
||||
|
||||
#include "BaseInterface.h"
|
||||
#include "StreamBuffer.h"
|
||||
|
||||
class StreamedInterface : public BaseInterface {
|
||||
public:
|
||||
StreamedInterface(uint streamBufferSize);
|
||||
virtual ~StreamedInterface();
|
||||
|
||||
protected:
|
||||
void flushStreamRx();
|
||||
uint32_t streamRxAvailableSize();
|
||||
uint32_t streamRxRead();
|
||||
|
||||
StreamBuffer _bufferRx;
|
||||
uint32_t _totalRemainingBytesToSend;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
56
firmware/source/interfaces/System.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "System.h"
|
||||
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
System::System()
|
||||
: _needReset(false), count(0){
|
||||
setInterfaceState(InterfaceState::INTIALIZED);
|
||||
}
|
||||
|
||||
System::~System() {
|
||||
|
||||
}
|
||||
|
||||
CmdStatus System::process(uint8_t const *cmd, uint8_t response[64]) {
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
|
||||
if(cmd[0] == Report::ID::SYS_RESET) {
|
||||
count = 0;
|
||||
_needReset = true;
|
||||
status = CmdStatus::OK;
|
||||
} else if(cmd[0] == Report::ID::SYS_GET_SN) {
|
||||
pico_unique_board_id_t board_id;
|
||||
pico_get_unique_board_id(&board_id);
|
||||
for (uint i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; ++i) {
|
||||
response[2+i] = board_id.id[i];
|
||||
}
|
||||
status = CmdStatus::OK;
|
||||
} else if(cmd[0] == Report::ID::SYS_GET_VN) {
|
||||
response[2] = PROJECT_VER_MAJOR;
|
||||
response[3] = PROJECT_VER_MINOR;
|
||||
response[4] = PROJECT_VER_PATCH;
|
||||
status = CmdStatus::OK;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
CmdStatus System::task(uint8_t response[64]) {
|
||||
(void)response;
|
||||
CmdStatus status = CmdStatus::NOT_CONCERNED;
|
||||
|
||||
if(_needReset) {
|
||||
count++; // give some time in event loop to send System ACK
|
||||
}
|
||||
|
||||
if(_needReset && count > 10) {
|
||||
watchdog_enable(10, 1);
|
||||
while(1);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||