├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── archives ├── images │ ├── CloudWatch Temperature Graph.png │ └── I2C Communication Repeated Start.jpg ├── motor_test.py ├── swift-3.1.1-RPi23-1604.tgz └── swift-4.0-Rpi23-1604-snapshot-5c06e85.tgz ├── datasheets ├── BCM2835_PDF_Datasheet.pdf ├── MCP3008.pdf ├── Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf └── ads1115.pdf ├── docs └── images │ └── TankTable.jpg ├── examples ├── BCM2835 │ ├── bcm2835.h │ └── module.modulemap ├── Rakefile ├── UnsafeMemory.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── steven_hepting.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── blink ├── blink_register.c ├── direct ├── directMemory.swift ├── direct_addressing.c ├── direct_old ├── failed │ ├── sht30 │ │ ├── SHT30 │ │ ├── sht30.c │ │ ├── sht30.py │ │ └── sht3xd.c │ └── temp_c │ │ ├── dht │ │ ├── dht.c │ │ ├── dht.py │ │ └── run.sh ├── hello ├── hello.swift ├── memory └── random.dat ├── source ├── Package.pins ├── Package.resolved ├── Package.swift ├── Rakefile └── Sources │ ├── Home │ ├── AnalogReader.swift │ ├── DataStore.swift │ ├── LightSwitch.swift │ └── i2cdetect.swift │ └── RaspberrySwift │ └── main.swift ├── tank ├── .gitignore ├── Package.pins ├── Package.swift ├── Sources │ └── RaspberryTank │ │ ├── Motor.swift │ │ ├── Tank.swift │ │ └── main.swift └── Tests │ ├── LinuxMain.swift │ └── raspberryTankTests │ └── raspberryTankTests.swift └── tooling ├── common.rb └── swift_build.rb /.gitattributes: -------------------------------------------------------------------------------- 1 | *.tgz filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | buck-out 3 | .buckd 4 | .build 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # raspberry-swift 2 | 3 | ![Image](docs/images/TankTable.jpg) 4 | 5 | Swift 3.1 app on the Raspberry Pi 3 6 | 7 | [![asciicast](https://asciinema.org/a/PXSoeFxyFvMVaBKC4M8BSSulF.png)](https://asciinema.org/a/PXSoeFxyFvMVaBKC4M8BSSulF) 8 | 9 | # Logging In & Building 10 | This command will search the local network by MAC address and find ones that belong to Raspberry Pi devices. 11 | 12 | ``` 13 | sudo arp-scan --localnet --interface=en0 | grep b8:27:eb: 14 | ``` 15 | 16 | To log in, you will likely need to pass along the username, and (in my case) pass along the particular RSA key you have set up on the device. 17 | 18 | ``` 19 | ssh steven@172.20.10.6 -i ~/.ssh/raspberry_rsa 20 | ``` 21 | 22 | Then to build and run the app: 23 | ``` 24 | cd tank 25 | swift build 26 | sudo ./.build/debug/RaspberrySwift 27 | ``` 28 | 29 | # Installing Swift 30 | ``` 31 | cd / 32 | wget https://github.com/shepting/raspberry-swift/blob/master/archives/swift-3.1.1-RPi23-1604.tgz 33 | sudo tar -xvzf swift-3.1.1-RPi23-1604.tgz 34 | sudo apt install clang 35 | sudo apt install libpython3.5-dev 36 | sudo apt install libcurl3 37 | ``` 38 | 39 | # Hardware Used 40 | - Rasberry PI 3 https://www.amazon.com/Raspberry-Model-1-2GHz-64-bit-quad-core/dp/B01CD5VC92 41 | - 32GB Micro-SD Card https://www.amazon.com/SanDisk-microSDHC-Standard-Packaging-SDSQUNC-032G-GN6MA/dp/B010Q57T02 42 | - Relay https://www.amazon.com/Tolako-Arduino-Indicator-Channel-Official/dp/B00VRUAHLE/ 43 | - 3.5" Monitor https://www.amazon.com/Raspberry-Display-kuman-480x320-Interface/dp/B01CNJVG8K 44 | - Keyboard + Trackpad https://www.amazon.com/Rii-Stainless-Wireless-Rechargable-Raspberry/dp/B00ESUXXZM 45 | - Raspberry Pi Breadboard & Mount https://www.amazon.com/Transparent-Experiment-Breadboard-Raspberry-Rapsbery/dp/B0155XBBFO 46 | 47 | # Talking Over I2C 48 | Sample Python configuration and bit shifting: https://github.com/switchdoclabs/SDL_Pi_Grove4Ch16BitADC/blob/58e2a8e32b03d2c463bde59821d210b16a792ad1/Adafruit_ADS1x15/Adafruit_ADS1x15.py#L266-L268 49 | 50 | # Resources 51 | - Umberto Raimondi (uraimo) "SwiftyGPIO" https://github.com/uraimo/SwiftyGPIO 52 | - Ray Fix "Unsafe Swift" https://www.raywenderlich.com/148569/unsafe-swift 53 | - Marius Rackwitz "Swift HomeKit Accessories" https://speakerdeck.com/marius/diy-smarthome-build-your-own-homekit-accessories 54 | - Nate Cook "Swift's Pointy Bits: Unsafe Swift and Pointer Types" https://academy.realm.io/posts/nate-cook-tryswift-tokyo-unsafe-swift-and-pointer-types/ 55 | - UnsafeMutablePointer https://developer.apple.com/documentation/swift/unsafemutablepointer 56 | 57 | -------------------------------------------------------------------------------- /archives/images/CloudWatch Temperature Graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/archives/images/CloudWatch Temperature Graph.png -------------------------------------------------------------------------------- /archives/images/I2C Communication Repeated Start.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/archives/images/I2C Communication Repeated Start.jpg -------------------------------------------------------------------------------- /archives/motor_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor 3 | from Adafruit_MotorHAT.Adafruit_PWM_Servo_Driver import PWM 4 | 5 | 6 | import time 7 | import atexit 8 | 9 | pwm = PWM(0x6f, debug=True) 10 | pwm.setPWMFreq(1600) 11 | 12 | # create a default object, no changes to I2C address or frequency 13 | mh = Adafruit_MotorHAT(addr=0x6f) 14 | 15 | 16 | # recommended for auto-disabling motors on shutdown! 17 | def turnOffMotors(): 18 | mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE) 19 | mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE) 20 | # mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE) 21 | # mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE) 22 | 23 | atexit.register(turnOffMotors) 24 | 25 | right = mh.getMotor(1) 26 | left = mh.getMotor(2) 27 | 28 | # set the speed to start, from 0 (off) to 255 (max speed) 29 | right.setSpeed(150) 30 | left.setSpeed(150) 31 | 32 | 33 | while (False): 34 | print "Forward! " 35 | right.run(Adafruit_MotorHAT.FORWARD) 36 | left.run(Adafruit_MotorHAT.FORWARD) 37 | 38 | print "\tSpeed up..." 39 | for i in range(255): 40 | right.setSpeed(i) 41 | left.setSpeed(i) 42 | time.sleep(0.01) 43 | 44 | print "\tSlow down..." 45 | for i in reversed(range(255)): 46 | right.setSpeed(i) 47 | left.setSpeed(i) 48 | time.sleep(0.01) 49 | 50 | print "Backward! " 51 | right.run(Adafruit_MotorHAT.BACKWARD) 52 | left.run(Adafruit_MotorHAT.BACKWARD) 53 | 54 | print "\tSpeed up..." 55 | for i in range(255): 56 | right.setSpeed(i) 57 | left.setSpeed(i) 58 | time.sleep(0.01) 59 | 60 | print "\tSlow down..." 61 | for i in reversed(range(255)): 62 | right.setSpeed(i) 63 | left.setSpeed(i) 64 | time.sleep(0.01) 65 | 66 | print "Release" 67 | right.run(Adafruit_MotorHAT.RELEASE) 68 | left.run(Adafruit_MotorHAT.RELEASE) 69 | time.sleep(1.0) 70 | 71 | 72 | -------------------------------------------------------------------------------- /archives/swift-3.1.1-RPi23-1604.tgz: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8b029a3a3071635ce52fbda631ea2c9620b409b87f24a2bb212626aa373221ca 3 | size 127339509 4 | -------------------------------------------------------------------------------- /archives/swift-4.0-Rpi23-1604-snapshot-5c06e85.tgz: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4d5226df6d14db3afd05c57e111cf80f15707ddf068adf1bd37489a854fa1017 3 | size 158631388 4 | -------------------------------------------------------------------------------- /datasheets/BCM2835_PDF_Datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/datasheets/BCM2835_PDF_Datasheet.pdf -------------------------------------------------------------------------------- /datasheets/MCP3008.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/datasheets/MCP3008.pdf -------------------------------------------------------------------------------- /datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf -------------------------------------------------------------------------------- /datasheets/ads1115.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/datasheets/ads1115.pdf -------------------------------------------------------------------------------- /docs/images/TankTable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/docs/images/TankTable.jpg -------------------------------------------------------------------------------- /examples/BCM2835/bcm2835.h: -------------------------------------------------------------------------------- 1 | /* bcm2835.h 2 | 3 | C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi 4 | 5 | Author: Mike McCauley 6 | Copyright (C) 2011-2013 Mike McCauley 7 | $Id: bcm2835.h,v 1.21 2017/02/05 02:08:07 mikem Exp mikem $ 8 | */ 9 | 10 | /*! \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi 11 | 12 | This is a C library for Raspberry Pi (RPi). It provides access to 13 | GPIO and other IO functions on the Broadcom BCM 2835 chip, as used in the RaspberryPi, 14 | allowing access to the GPIO pins on the 15 | 26 pin IDE plug on the RPi board so you can control and interface with various external devices. 16 | 17 | It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, 18 | and for accessing the system timers. 19 | Pin event detection is supported by polling (interrupts are not supported). 20 | 21 | It is C++ compatible, and installs as a header file and non-shared library on 22 | any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with 23 | BCM 2835). 24 | 25 | The version of the package that this documentation refers to can be downloaded 26 | from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.52.tar.gz 27 | You can find the latest version at http://www.airspayce.com/mikem/bcm2835 28 | 29 | Several example programs are provided. 30 | 31 | Based on data in http://elinux.org/RPi_Low-level_peripherals and 32 | http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf 33 | and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 34 | 35 | You can also find online help and discussion at http://groups.google.com/group/bcm2835 36 | Please use that group for all questions and discussions on this topic. 37 | Do not contact the author directly, unless it is to discuss commercial licensing. 38 | Before asking a question or reporting a bug, please read 39 | - http://en.wikipedia.org/wiki/Wikipedia:Reference_desk/How_to_ask_a_software_question 40 | - http://www.catb.org/esr/faqs/smart-questions.html 41 | - http://www.chiark.greenend.org.uk/~shgtatham/bugs.html 42 | 43 | Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian 44 | and Occidentalisv01, 2016-02-09 Raspbian Jessie. 45 | CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() 46 | are used and the pin is pulled LOW 47 | it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian 48 | and Occidentalisv01. 49 | Reason for this is not yet determined, but we suspect that an interrupt handler is 50 | hitting a hard loop on those OSs. 51 | If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with 52 | bcm2835_gpio_clr_len() and friends after use. 53 | 54 | \par Running as root 55 | 56 | Prior to the release of Raspbian Jessie in Feb 2016, access to any 57 | peripheral device via /dev/mem on the RPi required the process to 58 | run as root. Raspbian Jessie permits non-root users to access the 59 | GPIO peripheral (only) via /dev/gpiomem, and this library supports 60 | that limited mode of operation. 61 | 62 | If the library runs with effective UID of 0 (ie root), then 63 | bcm2835_init() will attempt to open /dev/mem, and, if successful, it 64 | will permit use of all peripherals and library functions. 65 | 66 | If the library runs with any other effective UID (ie not root), then 67 | bcm2835_init() will attempt to open /dev/gpiomem, and, if 68 | successful, will only permit GPIO operations. In particular, 69 | bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all 70 | other non-gpio operations may fail silently or crash. 71 | 72 | \par Installation 73 | 74 | This library consists of a single non-shared library and header file, which will be 75 | installed in the usual places by make install 76 | 77 | \code 78 | # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: 79 | tar zxvf bcm2835-1.xx.tar.gz 80 | cd bcm2835-1.xx 81 | ./configure 82 | make 83 | sudo make check 84 | sudo make install 85 | \endcode 86 | 87 | \par Physical Addresses 88 | 89 | The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() 90 | are low level peripheral register access functions. They are designed to use 91 | physical addresses as described in section 1.2.3 ARM physical addresses 92 | of the BCM2835 ARM Peripherals manual. 93 | Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus 94 | addresses for peripherals are set up to map onto the peripheral bus address range starting at 95 | 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at 96 | physical address 0x20nnnnnn. 97 | 98 | On RPI 2, the peripheral addresses are different and the bcm2835 library gets them 99 | from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2. 100 | 101 | After initialisation, the base address of the various peripheral 102 | registers are available with the following 103 | externals: 104 | bcm2835_gpio 105 | bcm2835_pwm 106 | bcm2835_clk 107 | bcm2835_pads 108 | bcm2835_spio0 109 | bcm2835_st 110 | bcm2835_bsc0 111 | bcm2835_bsc1 112 | 113 | \par Raspberry Pi 2 (RPI2) 114 | 115 | For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel. 116 | You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 117 | with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29. 118 | 119 | When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, 120 | and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). 121 | Without device tree support enabled and the presence of this file, it will not work on RPI2. 122 | 123 | To enable device tree support: 124 | 125 | \code 126 | sudo raspi-config 127 | under Advanced Options - enable Device Tree 128 | Reboot. 129 | \endcode 130 | 131 | \par Pin Numbering 132 | 133 | The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying 134 | BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs 135 | 136 | RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, 137 | as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the 138 | IDE header. 139 | 140 | RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. 141 | 142 | The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ 143 | the RPi pin number. There are symbolic definitions for each of the available pins 144 | that you should use for convenience. See \ref RPiGPIOPin. 145 | 146 | \par SPI Pins 147 | 148 | The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, 149 | allowing you to send and received data by SPI (Serial Peripheral Interface). 150 | For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus 151 | 152 | When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their 153 | default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able 154 | to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). 155 | When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be 156 | configured and controled with the usual bcm2835_gpio_* calls. 157 | 158 | The Raspberry Pi GPIO pins used for SPI are: 159 | 160 | - P1-19 (MOSI) 161 | - P1-21 (MISO) 162 | - P1-23 (CLK) 163 | - P1-24 (CE0) 164 | - P1-26 (CE1) 165 | 166 | Although it is possible to select high speeds for the SPI interface, up to 125MHz (see bcm2835_spi_setClockDivider()) 167 | you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the 168 | SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines 169 | ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz. 170 | Dont expect any speed faster than 31MHz to work reliably. 171 | 172 | \par I2C Pins 173 | 174 | The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, 175 | allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . 176 | For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C 177 | 178 | The Raspberry Pi V2 GPIO pins used for I2C are: 179 | 180 | - P1-03 (SDA) 181 | - P1-05 (SLC) 182 | 183 | \par PWM 184 | 185 | The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides 186 | functions for configuring and controlling PWM output on these pins. 187 | 188 | The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of 189 | GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): 190 | \code 191 | GPIO PIN RPi pin PWM Channel ALT FUN 192 | 12 0 0 193 | 13 1 0 194 | 18 1-12 0 5 195 | 19 1 5 196 | 40 0 0 197 | 41 1 0 198 | 45 1 0 199 | 52 0 1 200 | 53 1 1 201 | \endcode 202 | In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. 203 | Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) 204 | on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. 205 | Further it must be set to ALT FUN 5 to get PWM output. 206 | 207 | Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using 208 | bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). 209 | The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. 210 | Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio 211 | 212 | Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware 213 | sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. 214 | In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by 215 | LOW for RANGE-DATA clock pulses. 216 | 217 | The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from 218 | a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* 219 | values of \ref bcm2835PWMClockDivider. 220 | 221 | For example, say you wanted to drive a DC motor with PWM at about 1kHz, 222 | and control the speed in 1/1024 increments from 223 | 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the 224 | clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be 225 | 1.2MHz/1024 = 1171.875Hz. 226 | 227 | \par SPI 228 | 229 | In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using: 230 | 231 | \code 232 | sudo raspi-config 233 | under Advanced Options - enable Device Tree 234 | under Advanced Options - disable SPI 235 | Reboot. 236 | \endcode 237 | 238 | \par Real Time performance constraints 239 | 240 | The bcm2835 is a library for user programs (i.e. they run in 'userland'). 241 | Such programs are not part of the kernel and are usually 242 | subject to paging and swapping by the kernel while it does other things besides running your program. 243 | This means that you should not expect to get real-time performance or 244 | real-time timing constraints from such programs. In particular, there is no guarantee that the 245 | bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. 246 | In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times 247 | than the one you asked for. So please dont expect to get exactly the time delay you request. 248 | 249 | Arjan reports that you can prevent swapping on Linux with the following code fragment: 250 | 251 | \code 252 | struct sched_param sp; 253 | memset(&sp, 0, sizeof(sp)); 254 | sp.sched_priority = sched_get_priority_max(SCHED_FIFO); 255 | sched_setscheduler(0, SCHED_FIFO, &sp); 256 | mlockall(MCL_CURRENT | MCL_FUTURE); 257 | \endcode 258 | 259 | \par Bindings to other languages 260 | 261 | mikem has made Perl bindings available at CPAN: 262 | http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm 263 | Matthew Baker has kindly made Python bindings available at: 264 | https: github.com/mubeta06/py-libbcm2835 265 | Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility 266 | for Raspberry Pi, based on the bcm2835 library. The 267 | utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a 268 | free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ 269 | 270 | \par Open Source Licensing GPL V2 271 | 272 | This is the appropriate option if you want to share the source code of your 273 | application with everyone you distribute it to, and you also want to give them 274 | the right to share who uses it. If you wish to use this software under Open 275 | Source Licensing, you must contribute all your source code to the open source 276 | community in accordance with the GPL Version 2 when your application is 277 | distributed. See https://www.gnu.org/licenses/gpl-2.0.html and COPYING 278 | 279 | \par Commercial Licensing 280 | 281 | This is the appropriate option if you are creating proprietary applications 282 | and you are not prepared to distribute and share the source code of your 283 | application. Purchase commercial licenses at http://airspayce.binpress.com 284 | 285 | 286 | \par Acknowledgements 287 | 288 | Some of this code has been inspired by Dom and Gert. 289 | The I2C code has been inspired by Alan Barr. 290 | 291 | \par Revision History 292 | 293 | \version 1.0 Initial release 294 | 295 | \version 1.1 Minor bug fixes 296 | 297 | \version 1.2 Added support for SPI 298 | 299 | \version 1.3 Added bcm2835_spi_transfern() 300 | 301 | \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. 302 | 303 | \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz 304 | 305 | \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 306 | Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() 307 | bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now 308 | changes only the pin specified. Other pins that were already previously 309 | enabled stay enabled. 310 | Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() 311 | bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() 312 | to clear the enable for individual pins, suggested by Andreas Sundstrom. 313 | 314 | \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. 315 | 316 | \version 1.8 Improvements to read barrier, as suggested by maddin. 317 | 318 | \version 1.9 Improvements contributed by mikew: 319 | I noticed that it was mallocing memory for the mmaps on /dev/mem. 320 | It's not necessary to do that, you can just mmap the file directly, 321 | so I've removed the mallocs (and frees). 322 | I've also modified delayMicroseconds() to use nanosleep() for long waits, 323 | and a busy wait on a high resolution timer for the rest. This is because 324 | I've found that calling nanosleep() takes at least 100-200 us. 325 | You need to link using '-lrt' using this version. 326 | I've added some unsigned casts to the debug prints to silence compiler 327 | warnings I was getting, fixed some typos, and changed the value of 328 | BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at 329 | http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 330 | Also added a define for the passwrd value that Gert says is needed to 331 | change pad control settings. 332 | 333 | \version 1.10 Changed the names of the delay functions to bcm2835_delay() 334 | and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. 335 | Macros to map delay()-> bcm2835_delay() and 336 | Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which 337 | can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY 338 | 339 | \version 1.11 Fixed incorrect link to download file 340 | 341 | \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) 342 | 343 | \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 344 | Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio 345 | bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. 346 | 347 | \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. 348 | Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. 349 | Reported by Ben Simpson. 350 | 351 | \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. 352 | 353 | \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi 354 | to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. 355 | 356 | \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. 357 | 358 | \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: 359 | now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. 360 | No need to link with -lrt now. Contributed by Arjan van Vught. 361 | \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. 362 | Reported by olly. 363 | 364 | \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. 365 | 366 | \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. 367 | Patch courtesy Jeremy Mortis. 368 | 369 | \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set 370 | falling edge events. Reported by Mark Dootson. 371 | 372 | \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. 373 | Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions 374 | to fix ocasional reads not completing. Patched by Mark Dootson. 375 | 376 | \version 1.24 Mark Dootson p[atched a problem with his previously submitted code 377 | under high load from other processes. 378 | 379 | \version 1.25 Updated author and distribution location details to airspayce.com 380 | 381 | \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. 382 | Reported by Hartmut Henkel. 383 | 384 | \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is 385 | now automatically included. 386 | Added suport for PWM mode with bcm2835_pwm_* functions. 387 | 388 | \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than 389 | 64 bytes dues to read buffer filling. Patched by Peter Würtz. 390 | 391 | \version 1.29 Further fix to SPI from Peter Würtz. 392 | 393 | \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for 394 | significant performance improvements, Patch by Alan Watson. 395 | 396 | \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. 397 | 398 | \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. 399 | By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. 400 | Contributed by Malcolm Wiles based on work by Arvi Govindaraj. 401 | 402 | \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. 403 | 404 | \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, 405 | sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. 406 | 407 | \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas. 408 | 409 | \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second 410 | one makes us skip the test when using fakeroot (as used when building 411 | Debian packages). Contributed by Guido Günther. 412 | 413 | \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.
414 | Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.
415 | Added definitions for Raspberry Pi B+ J8 header GPIO pins.
416 | 417 | \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
418 | 419 | \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. 420 | Testers please confirm correct operation on RPi2.
421 | Unneccessary 'volatile' qualifiers removed from all variables and signatures.
422 | Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.
423 | Minor improvements to spi.c example.
424 | 425 | \version 1.40 Correct operation on RPi2 has been confirmed.
426 | Fixed a number of compiler errors and warnings that occur when bcm2835.h is included 427 | in code compiled with -Wall -Woverflow -Wstrict-overflow -Wshadow -Wextra -pedantic. 428 | Reported by tlhackque.
429 | Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.
430 | Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.
431 | 432 | \version 1.41 Added BCM2835_VERSION macro and new function bcm2835_version(); Requested by tlhackque.
433 | Improvements to peripheral memory barriers as suggested by tlhackque.
434 | Reinstated some necessary volatile declarations as requested by tlhackque.
435 | 436 | \version 1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.
437 | 438 | \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. 439 | Reported and patched by Lars Christensen.
440 | Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.
441 | 442 | \version 1.44 Added documention about the need for device tree to be enabled on RPI2.
443 | Improvements to detection of availablity of DMB instruction based on value of __ARM_ARCH macro.
444 | 445 | \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() 446 | and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido. 447 | 448 | \version 1.46 2015-09-18 449 | Added symbolic definitions for remaining pins on 40 pin GPIO header on RPi 2.
450 | 451 | \version 1.47 2015-11-18 452 | Fixed possibly incorrect reads in bcm2835_i2c_read_register_rs, patch from Eckhardt Ulrich.
453 | 454 | \version 1.48 2015-12-08 455 | Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs 456 | and others. 457 | 458 | \version 1.49 2016-01-05 459 | Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi(). 460 | 461 | \version 1.50 2016-02-28 462 | Added support for running as non-root, permitting access to GPIO only. Functions 463 | bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root 464 | (which prevents access to the SPI and I2C peripherals, amongst others). 465 | Testing on Raspbian Jessie. 466 | 467 | \version 1.51 2016-11-03 468 | Added documentation about SPI clock divider and resulting SPI speeds on RPi3. 469 | Fixed a problem where seg fault could occur in bcm2835_delayMicroseconds() if not running as root. Patch from Pok. 470 | 471 | \version 1.52 2017-02-03 472 | Added link to commercial license purchasing. 473 | 474 | \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS 475 | */ 476 | 477 | 478 | /* Defines for BCM2835 */ 479 | #ifndef BCM2835_H 480 | #define BCM2835_H 481 | 482 | #include 483 | 484 | #define BCM2835_VERSION 10052 /* Version 1.52 */ 485 | 486 | /* RPi 2 is ARM v7, and has DMB instruction for memory barriers. 487 | Older RPis are ARM v6 and don't, so a coprocessor instruction must be used instead. 488 | However, not all versions of gcc in all distros support the dmb assembler instruction even on conmpatible processors. 489 | This test is so any ARMv7 or higher processors with suitable GCC will use DMB. 490 | */ 491 | #if __ARM_ARCH >= 7 492 | #define BCM2835_HAVE_DMB 493 | #endif 494 | 495 | /*! \defgroup constants Constants for passing to and from library functions 496 | The values here are designed to be passed to various functions in the bcm2835 library. 497 | @{ 498 | */ 499 | 500 | /*! This means pin HIGH, true, 3.3volts on a pin. */ 501 | #define HIGH 0x1 502 | /*! This means pin LOW, false, 0volts on a pin. */ 503 | #define LOW 0x0 504 | 505 | /*! Speed of the core clock core_clk */ 506 | #define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */ 507 | 508 | /*! On RPi2 with BCM2836, and all recent OSs, the base of the peripherals is read from a /proc file */ 509 | #define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges" 510 | /*! Offset into BMC2835_RPI2_DT_FILENAME for the peripherals base address */ 511 | #define BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET 4 512 | /*! Offset into BMC2835_RPI2_DT_FILENAME for the peripherals size address */ 513 | #define BMC2835_RPI2_DT_PERI_SIZE_OFFSET 8 514 | 515 | /*! Physical addresses for various peripheral register sets 516 | Base Physical Address of the BCM 2835 peripheral registers 517 | Note this is different for the RPi2 BCM2836, where this is derived from /proc/device-tree/soc/ranges 518 | If /proc/device-tree/soc/ranges exists on a RPi 1 OS, it would be expected to contain the 519 | following numbers: 520 | */ 521 | /*! Peripherals block base address on RPi 1 */ 522 | #define BCM2835_PERI_BASE 0x20000000 523 | /*! Size of the peripherals block on RPi 1 */ 524 | #define BCM2835_PERI_SIZE 0x01000000 525 | 526 | /*! Offsets for the bases of various peripherals within the peripherals block 527 | / Base Address of the System Timer registers 528 | */ 529 | #define BCM2835_ST_BASE 0x3000 530 | /*! Base Address of the Pads registers */ 531 | #define BCM2835_GPIO_PADS 0x100000 532 | /*! Base Address of the Clock/timer registers */ 533 | #define BCM2835_CLOCK_BASE 0x101000 534 | /*! Base Address of the GPIO registers */ 535 | #define BCM2835_GPIO_BASE 0x200000 536 | /*! Base Address of the SPI0 registers */ 537 | #define BCM2835_SPI0_BASE 0x204000 538 | /*! Base Address of the BSC0 registers */ 539 | #define BCM2835_BSC0_BASE 0x205000 540 | /*! Base Address of the PWM registers */ 541 | #define BCM2835_GPIO_PWM 0x20C000 542 | /*! Base Address of the BSC1 registers */ 543 | #define BCM2835_BSC1_BASE 0x804000 544 | 545 | /*! Physical address and size of the peripherals block 546 | May be overridden on RPi2 547 | */ 548 | extern uint32_t *bcm2835_peripherals_base; 549 | /*! Size of the peripherals block to be mapped */ 550 | extern uint32_t bcm2835_peripherals_size; 551 | 552 | /*! Virtual memory address of the mapped peripherals block */ 553 | extern uint32_t *bcm2835_peripherals; 554 | 555 | /*! Base of the ST (System Timer) registers. 556 | Available after bcm2835_init has been called (as root) 557 | */ 558 | extern volatile uint32_t *bcm2835_st; 559 | 560 | /*! Base of the GPIO registers. 561 | Available after bcm2835_init has been called 562 | */ 563 | extern volatile uint32_t *bcm2835_gpio; 564 | 565 | /*! Base of the PWM registers. 566 | Available after bcm2835_init has been called (as root) 567 | */ 568 | extern volatile uint32_t *bcm2835_pwm; 569 | 570 | /*! Base of the CLK registers. 571 | Available after bcm2835_init has been called (as root) 572 | */ 573 | extern volatile uint32_t *bcm2835_clk; 574 | 575 | /*! Base of the PADS registers. 576 | Available after bcm2835_init has been called (as root) 577 | */ 578 | extern volatile uint32_t *bcm2835_pads; 579 | 580 | /*! Base of the SPI0 registers. 581 | Available after bcm2835_init has been called (as root) 582 | */ 583 | extern volatile uint32_t *bcm2835_spi0; 584 | 585 | /*! Base of the BSC0 registers. 586 | Available after bcm2835_init has been called (as root) 587 | */ 588 | extern volatile uint32_t *bcm2835_bsc0; 589 | 590 | /*! Base of the BSC1 registers. 591 | Available after bcm2835_init has been called (as root) 592 | */ 593 | extern volatile uint32_t *bcm2835_bsc1; 594 | 595 | /*! \brief bcm2835RegisterBase 596 | Register bases for bcm2835_regbase() 597 | */ 598 | typedef enum 599 | { 600 | BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ 601 | BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ 602 | BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ 603 | BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ 604 | BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */ 605 | BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */ 606 | BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */ 607 | BCM2835_REGBASE_BSC1 = 8 /*!< Base of the BSC1 registers. */ 608 | } bcm2835RegisterBase; 609 | 610 | /*! Size of memory page on RPi */ 611 | #define BCM2835_PAGE_SIZE (4*1024) 612 | /*! Size of memory block on RPi */ 613 | #define BCM2835_BLOCK_SIZE (4*1024) 614 | 615 | 616 | /* Defines for GPIO 617 | The BCM2835 has 54 GPIO pins. 618 | BCM2835 data sheet, Page 90 onwards. 619 | */ 620 | /*! GPIO register offsets from BCM2835_GPIO_BASE. 621 | Offsets into the GPIO Peripheral block in bytes per 6.1 Register View 622 | */ 623 | #define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */ 624 | #define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */ 625 | #define BCM2835_GPFSEL2 0x0008 /*!< GPIO Function Select 2 */ 626 | #define BCM2835_GPFSEL3 0x000c /*!< GPIO Function Select 3 */ 627 | #define BCM2835_GPFSEL4 0x0010 /*!< GPIO Function Select 4 */ 628 | #define BCM2835_GPFSEL5 0x0014 /*!< GPIO Function Select 5 */ 629 | #define BCM2835_GPSET0 0x001c /*!< GPIO Pin Output Set 0 */ 630 | #define BCM2835_GPSET1 0x0020 /*!< GPIO Pin Output Set 1 */ 631 | #define BCM2835_GPCLR0 0x0028 /*!< GPIO Pin Output Clear 0 */ 632 | #define BCM2835_GPCLR1 0x002c /*!< GPIO Pin Output Clear 1 */ 633 | #define BCM2835_GPLEV0 0x0034 /*!< GPIO Pin Level 0 */ 634 | #define BCM2835_GPLEV1 0x0038 /*!< GPIO Pin Level 1 */ 635 | #define BCM2835_GPEDS0 0x0040 /*!< GPIO Pin Event Detect Status 0 */ 636 | #define BCM2835_GPEDS1 0x0044 /*!< GPIO Pin Event Detect Status 1 */ 637 | #define BCM2835_GPREN0 0x004c /*!< GPIO Pin Rising Edge Detect Enable 0 */ 638 | #define BCM2835_GPREN1 0x0050 /*!< GPIO Pin Rising Edge Detect Enable 1 */ 639 | #define BCM2835_GPFEN0 0x0058 /*!< GPIO Pin Falling Edge Detect Enable 0 */ 640 | #define BCM2835_GPFEN1 0x005c /*!< GPIO Pin Falling Edge Detect Enable 1 */ 641 | #define BCM2835_GPHEN0 0x0064 /*!< GPIO Pin High Detect Enable 0 */ 642 | #define BCM2835_GPHEN1 0x0068 /*!< GPIO Pin High Detect Enable 1 */ 643 | #define BCM2835_GPLEN0 0x0070 /*!< GPIO Pin Low Detect Enable 0 */ 644 | #define BCM2835_GPLEN1 0x0074 /*!< GPIO Pin Low Detect Enable 1 */ 645 | #define BCM2835_GPAREN0 0x007c /*!< GPIO Pin Async. Rising Edge Detect 0 */ 646 | #define BCM2835_GPAREN1 0x0080 /*!< GPIO Pin Async. Rising Edge Detect 1 */ 647 | #define BCM2835_GPAFEN0 0x0088 /*!< GPIO Pin Async. Falling Edge Detect 0 */ 648 | #define BCM2835_GPAFEN1 0x008c /*!< GPIO Pin Async. Falling Edge Detect 1 */ 649 | #define BCM2835_GPPUD 0x0094 /*!< GPIO Pin Pull-up/down Enable */ 650 | #define BCM2835_GPPUDCLK0 0x0098 /*!< GPIO Pin Pull-up/down Enable Clock 0 */ 651 | #define BCM2835_GPPUDCLK1 0x009c /*!< GPIO Pin Pull-up/down Enable Clock 1 */ 652 | 653 | /*! \brief bcm2835PortFunction 654 | Port function select modes for bcm2835_gpio_fsel() 655 | */ 656 | typedef enum 657 | { 658 | BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ 659 | BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ 660 | BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ 661 | BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ 662 | BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ 663 | BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ 664 | BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ 665 | BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ 666 | BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ 667 | } bcm2835FunctionSelect; 668 | 669 | /*! \brief bcm2835PUDControl 670 | Pullup/Pulldown defines for bcm2835_gpio_pud() 671 | */ 672 | typedef enum 673 | { 674 | BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ 675 | BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ 676 | BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ 677 | } bcm2835PUDControl; 678 | 679 | /*! Pad control register offsets from BCM2835_GPIO_PADS */ 680 | #define BCM2835_PADS_GPIO_0_27 0x002c /*!< Pad control register for pads 0 to 27 */ 681 | #define BCM2835_PADS_GPIO_28_45 0x0030 /*!< Pad control register for pads 28 to 45 */ 682 | #define BCM2835_PADS_GPIO_46_53 0x0034 /*!< Pad control register for pads 46 to 53 */ 683 | 684 | /*! Pad Control masks */ 685 | #define BCM2835_PAD_PASSWRD (0x5A << 24) /*!< Password to enable setting pad mask */ 686 | #define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 /*!< Slew rate unlimited */ 687 | #define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 /*!< Hysteresis enabled */ 688 | #define BCM2835_PAD_DRIVE_2mA 0x00 /*!< 2mA drive current */ 689 | #define BCM2835_PAD_DRIVE_4mA 0x01 /*!< 4mA drive current */ 690 | #define BCM2835_PAD_DRIVE_6mA 0x02 /*!< 6mA drive current */ 691 | #define BCM2835_PAD_DRIVE_8mA 0x03 /*!< 8mA drive current */ 692 | #define BCM2835_PAD_DRIVE_10mA 0x04 /*!< 10mA drive current */ 693 | #define BCM2835_PAD_DRIVE_12mA 0x05 /*!< 12mA drive current */ 694 | #define BCM2835_PAD_DRIVE_14mA 0x06 /*!< 14mA drive current */ 695 | #define BCM2835_PAD_DRIVE_16mA 0x07 /*!< 16mA drive current */ 696 | 697 | /*! \brief bcm2835PadGroup 698 | Pad group specification for bcm2835_gpio_pad() 699 | */ 700 | typedef enum 701 | { 702 | BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ 703 | BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ 704 | BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ 705 | } bcm2835PadGroup; 706 | 707 | /*! \brief GPIO Pin Numbers 708 | 709 | Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. 710 | These can be passed as a pin number to any function requiring a pin. 711 | Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins 712 | and some can adopt an alternate function. 713 | RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. 714 | RPi B+ has yet differnet pinouts and these are defined in RPI_BPLUS_*. 715 | At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively 716 | When SPI0 is in use (ie after bcm2835_spi_begin()), SPI0 pins are dedicated to SPI 717 | and cant be controlled independently. 718 | If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these 719 | symbolic names 720 | */ 721 | typedef enum 722 | { 723 | RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ 724 | RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ 725 | RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ 726 | RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ 727 | RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ 728 | RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ 729 | RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ 730 | RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ 731 | RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ 732 | RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ 733 | RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ 734 | RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ 735 | RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ 736 | RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ 737 | RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ 738 | RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ 739 | RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ 740 | 741 | /* RPi Version 2 */ 742 | RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ 743 | RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ 744 | RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ 745 | RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ 746 | RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ 747 | RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ 748 | RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ 749 | RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ 750 | RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ 751 | RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ 752 | RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ 753 | RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ 754 | RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ 755 | RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ 756 | RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ 757 | RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ 758 | RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ 759 | RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ 760 | RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ 761 | RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ 762 | RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ 763 | RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */ 764 | RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ 765 | RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ 766 | RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ 767 | RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ 768 | 769 | /* RPi Version 2, new plug P5 */ 770 | RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ 771 | RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ 772 | RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ 773 | RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ 774 | 775 | /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ 776 | RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ 777 | RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ 778 | RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ 779 | RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ 780 | RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ 781 | RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ 782 | RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ 783 | RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ 784 | RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ 785 | RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ 786 | RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ 787 | RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ 788 | RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ 789 | RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ 790 | RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ 791 | RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ 792 | RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ 793 | RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ 794 | RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ 795 | RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ 796 | RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ 797 | RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */ 798 | RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ 799 | RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ 800 | RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ 801 | RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ 802 | } RPiGPIOPin; 803 | 804 | /* Defines for SPI 805 | GPIO register offsets from BCM2835_SPI0_BASE. 806 | Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map 807 | */ 808 | #define BCM2835_SPI0_CS 0x0000 /*!< SPI Master Control and Status */ 809 | #define BCM2835_SPI0_FIFO 0x0004 /*!< SPI Master TX and RX FIFOs */ 810 | #define BCM2835_SPI0_CLK 0x0008 /*!< SPI Master Clock Divider */ 811 | #define BCM2835_SPI0_DLEN 0x000c /*!< SPI Master Data Length */ 812 | #define BCM2835_SPI0_LTOH 0x0010 /*!< SPI LOSSI mode TOH */ 813 | #define BCM2835_SPI0_DC 0x0014 /*!< SPI DMA DREQ Controls */ 814 | 815 | /* Register masks for SPI0_CS */ 816 | #define BCM2835_SPI0_CS_LEN_LONG 0x02000000 /*!< Enable Long data word in Lossi mode if DMA_LEN is set */ 817 | #define BCM2835_SPI0_CS_DMA_LEN 0x01000000 /*!< Enable DMA mode in Lossi mode */ 818 | #define BCM2835_SPI0_CS_CSPOL2 0x00800000 /*!< Chip Select 2 Polarity */ 819 | #define BCM2835_SPI0_CS_CSPOL1 0x00400000 /*!< Chip Select 1 Polarity */ 820 | #define BCM2835_SPI0_CS_CSPOL0 0x00200000 /*!< Chip Select 0 Polarity */ 821 | #define BCM2835_SPI0_CS_RXF 0x00100000 /*!< RXF - RX FIFO Full */ 822 | #define BCM2835_SPI0_CS_RXR 0x00080000 /*!< RXR RX FIFO needs Reading (full) */ 823 | #define BCM2835_SPI0_CS_TXD 0x00040000 /*!< TXD TX FIFO can accept Data */ 824 | #define BCM2835_SPI0_CS_RXD 0x00020000 /*!< RXD RX FIFO contains Data */ 825 | #define BCM2835_SPI0_CS_DONE 0x00010000 /*!< Done transfer Done */ 826 | #define BCM2835_SPI0_CS_TE_EN 0x00008000 /*!< Unused */ 827 | #define BCM2835_SPI0_CS_LMONO 0x00004000 /*!< Unused */ 828 | #define BCM2835_SPI0_CS_LEN 0x00002000 /*!< LEN LoSSI enable */ 829 | #define BCM2835_SPI0_CS_REN 0x00001000 /*!< REN Read Enable */ 830 | #define BCM2835_SPI0_CS_ADCS 0x00000800 /*!< ADCS Automatically Deassert Chip Select */ 831 | #define BCM2835_SPI0_CS_INTR 0x00000400 /*!< INTR Interrupt on RXR */ 832 | #define BCM2835_SPI0_CS_INTD 0x00000200 /*!< INTD Interrupt on Done */ 833 | #define BCM2835_SPI0_CS_DMAEN 0x00000100 /*!< DMAEN DMA Enable */ 834 | #define BCM2835_SPI0_CS_TA 0x00000080 /*!< Transfer Active */ 835 | #define BCM2835_SPI0_CS_CSPOL 0x00000040 /*!< Chip Select Polarity */ 836 | #define BCM2835_SPI0_CS_CLEAR 0x00000030 /*!< Clear FIFO Clear RX and TX */ 837 | #define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 /*!< Clear FIFO Clear RX */ 838 | #define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 /*!< Clear FIFO Clear TX */ 839 | #define BCM2835_SPI0_CS_CPOL 0x00000008 /*!< Clock Polarity */ 840 | #define BCM2835_SPI0_CS_CPHA 0x00000004 /*!< Clock Phase */ 841 | #define BCM2835_SPI0_CS_CS 0x00000003 /*!< Chip Select */ 842 | 843 | /*! \brief bcm2835SPIBitOrder SPI Bit order 844 | Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() 845 | */ 846 | typedef enum 847 | { 848 | BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ 849 | BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ 850 | }bcm2835SPIBitOrder; 851 | 852 | /*! \brief SPI Data mode 853 | Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() 854 | */ 855 | typedef enum 856 | { 857 | BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ 858 | BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ 859 | BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ 860 | BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ 861 | }bcm2835SPIMode; 862 | 863 | /*! \brief bcm2835SPIChipSelect 864 | Specify the SPI chip select pin(s) 865 | */ 866 | typedef enum 867 | { 868 | BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ 869 | BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ 870 | BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ 871 | BCM2835_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ 872 | } bcm2835SPIChipSelect; 873 | 874 | /*! \brief bcm2835SPIClockDivider 875 | Specifies the divider used to generate the SPI clock from the system clock. 876 | Figures below give the divider, clock period and clock frequency. 877 | Clock divided is based on nominal core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3. 878 | It is reported that (contrary to the documentation) any even divider may used. 879 | The frequencies shown for each divider have been confirmed by measurement on RPi1 and RPi2. 880 | The system clock frequency on RPi3 is different, so the frequency you get from a given divider will be different. 881 | See comments in 'SPI Pins' for information about reliable SPI speeds. 882 | Note: it is possible to change the core clock rate of the RPi 3 back to 250MHz, by putting 883 | \code 884 | core_freq=250 885 | \endcode 886 | in the config.txt 887 | */ 888 | typedef enum 889 | { 890 | BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ 891 | BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ 892 | BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ 893 | BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ 894 | BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ 895 | BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ 896 | BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ 897 | BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ 898 | BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ 899 | BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ 900 | BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ 901 | BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ 902 | BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ 903 | BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ 904 | BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ 905 | BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ 906 | BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ 907 | } bcm2835SPIClockDivider; 908 | 909 | /* Defines for I2C 910 | GPIO register offsets from BCM2835_BSC*_BASE. 911 | Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map 912 | */ 913 | #define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */ 914 | #define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */ 915 | #define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ 916 | #define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */ 917 | #define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ 918 | #define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ 919 | #define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ 920 | #define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ 921 | 922 | /* Register masks for BSC_C */ 923 | #define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ 924 | #define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ 925 | #define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ 926 | #define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ 927 | #define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ 928 | #define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ 929 | #define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ 930 | #define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */ 931 | 932 | /* Register masks for BSC_S */ 933 | #define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ 934 | #define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */ 935 | #define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ 936 | #define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ 937 | #define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ 938 | #define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ 939 | #define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ 940 | #define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ 941 | #define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ 942 | #define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */ 943 | 944 | #define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ 945 | 946 | /*! \brief bcm2835I2CClockDivider 947 | Specifies the divider used to generate the I2C clock from the system clock. 948 | Clock divided is based on nominal base clock rate of 250MHz 949 | */ 950 | typedef enum 951 | { 952 | BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ 953 | BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ 954 | BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ 955 | BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ 956 | } bcm2835I2CClockDivider; 957 | 958 | /*! \brief bcm2835I2CReasonCodes 959 | Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. 960 | */ 961 | typedef enum 962 | { 963 | BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ 964 | BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ 965 | BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ 966 | BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ 967 | } bcm2835I2CReasonCodes; 968 | 969 | /* Defines for ST 970 | GPIO register offsets from BCM2835_ST_BASE. 971 | Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers 972 | The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. 973 | BCM2835_ST_CLO is the System Timer Counter Lower bits register. 974 | The system timer free-running counter lower register is a read-only register that returns the current value 975 | of the lower 32-bits of the free running counter. 976 | BCM2835_ST_CHI is the System Timer Counter Upper bits register. 977 | The system timer free-running counter upper register is a read-only register that returns the current value 978 | of the upper 32-bits of the free running counter. 979 | */ 980 | #define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */ 981 | #define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ 982 | #define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ 983 | 984 | /*! @} */ 985 | 986 | 987 | /* Defines for PWM, word offsets (ie 4 byte multiples) */ 988 | #define BCM2835_PWM_CONTROL 0 989 | #define BCM2835_PWM_STATUS 1 990 | #define BCM2835_PWM_DMAC 2 991 | #define BCM2835_PWM0_RANGE 4 992 | #define BCM2835_PWM0_DATA 5 993 | #define BCM2835_PWM_FIF1 6 994 | #define BCM2835_PWM1_RANGE 8 995 | #define BCM2835_PWM1_DATA 9 996 | 997 | /* Defines for PWM Clock, word offsets (ie 4 byte multiples) */ 998 | #define BCM2835_PWMCLK_CNTL 40 999 | #define BCM2835_PWMCLK_DIV 41 1000 | #define BCM2835_PWM_PASSWRD (0x5A << 24) /*!< Password to enable setting PWM clock */ 1001 | 1002 | #define BCM2835_PWM1_MS_MODE 0x8000 /*!< Run in Mark/Space mode */ 1003 | #define BCM2835_PWM1_USEFIFO 0x2000 /*!< Data from FIFO */ 1004 | #define BCM2835_PWM1_REVPOLAR 0x1000 /*!< Reverse polarity */ 1005 | #define BCM2835_PWM1_OFFSTATE 0x0800 /*!< Ouput Off state */ 1006 | #define BCM2835_PWM1_REPEATFF 0x0400 /*!< Repeat last value if FIFO empty */ 1007 | #define BCM2835_PWM1_SERIAL 0x0200 /*!< Run in serial mode */ 1008 | #define BCM2835_PWM1_ENABLE 0x0100 /*!< Channel Enable */ 1009 | 1010 | #define BCM2835_PWM0_MS_MODE 0x0080 /*!< Run in Mark/Space mode */ 1011 | #define BCM2835_PWM_CLEAR_FIFO 0x0040 /*!< Clear FIFO */ 1012 | #define BCM2835_PWM0_USEFIFO 0x0020 /*!< Data from FIFO */ 1013 | #define BCM2835_PWM0_REVPOLAR 0x0010 /*!< Reverse polarity */ 1014 | #define BCM2835_PWM0_OFFSTATE 0x0008 /*!< Ouput Off state */ 1015 | #define BCM2835_PWM0_REPEATFF 0x0004 /*!< Repeat last value if FIFO empty */ 1016 | #define BCM2835_PWM0_SERIAL 0x0002 /*!< Run in serial mode */ 1017 | #define BCM2835_PWM0_ENABLE 0x0001 /*!< Channel Enable */ 1018 | 1019 | /*! \brief bcm2835PWMClockDivider 1020 | Specifies the divider used to generate the PWM clock from the system clock. 1021 | Figures below give the divider, clock period and clock frequency. 1022 | Clock divided is based on nominal PWM base clock rate of 19.2MHz 1023 | The frequencies shown for each divider have been confirmed by measurement 1024 | */ 1025 | typedef enum 1026 | { 1027 | BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ 1028 | BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ 1029 | BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ 1030 | BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ 1031 | BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ 1032 | BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ 1033 | BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ 1034 | BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ 1035 | BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ 1036 | BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ 1037 | BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ 1038 | BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ 1039 | } bcm2835PWMClockDivider; 1040 | 1041 | /* Historical name compatibility */ 1042 | #ifndef BCM2835_NO_DELAY_COMPATIBILITY 1043 | #define delay(x) bcm2835_delay(x) 1044 | #define delayMicroseconds(x) bcm2835_delayMicroseconds(x) 1045 | #endif 1046 | 1047 | #ifdef __cplusplus 1048 | extern "C" { 1049 | #endif 1050 | 1051 | /*! \defgroup init Library initialisation and management 1052 | These functions allow you to intialise and control the bcm2835 library 1053 | @{ 1054 | */ 1055 | 1056 | /*! Initialise the library by opening /dev/mem (if you are root) 1057 | or /dev/gpiomem (if you are not) 1058 | and getting pointers to the 1059 | internal memory for BCM 2835 device registers. You must call this (successfully) 1060 | before calling any other 1061 | functions in this library (except bcm2835_set_debug). 1062 | If bcm2835_init() fails by returning 0, 1063 | calling any other function may result in crashes or other failures. 1064 | If bcm2835_init() succeeds but you are not running as root, then only gpio operations 1065 | are permitted, and calling any other functions may result in crashes or other failures. . 1066 | Prints messages to stderr in case of errors. 1067 | \return 1 if successful else 0 1068 | */ 1069 | extern int bcm2835_init(void); 1070 | 1071 | /*! Close the library, deallocating any allocated memory and closing /dev/mem 1072 | \return 1 if successful else 0 1073 | */ 1074 | extern int bcm2835_close(void); 1075 | 1076 | /*! Sets the debug level of the library. 1077 | A value of 1 prevents mapping to /dev/mem, and makes the library print out 1078 | what it would do, rather than accessing the GPIO registers. 1079 | A value of 0, the default, causes normal operation. 1080 | Call this before calling bcm2835_init(); 1081 | \param[in] debug The new debug level. 1 means debug 1082 | */ 1083 | extern void bcm2835_set_debug(uint8_t debug); 1084 | 1085 | /*! Returns the version number of the library, same as BCM2835_VERSION 1086 | \return the current library version number 1087 | */ 1088 | extern unsigned int bcm2835_version(void); 1089 | 1090 | /*! @} */ 1091 | 1092 | /*! \defgroup lowlevel Low level register access 1093 | These functions provide low level register access, and should not generally 1094 | need to be used 1095 | 1096 | @{ 1097 | */ 1098 | 1099 | /*! Gets the base of a register 1100 | \param[in] regbase You can use one of the common values BCM2835_REGBASE_* 1101 | in \ref bcm2835RegisterBase 1102 | \return the register base 1103 | \sa Physical Addresses 1104 | */ 1105 | extern uint32_t* bcm2835_regbase(uint8_t regbase); 1106 | 1107 | /*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. 1108 | This is safe, but slow. The MB before protects this read from any in-flight reads that didn't 1109 | use a MB. The MB after protects subsequent reads from another peripheral. 1110 | 1111 | \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. 1112 | \return the value read from the 32 bit register 1113 | \sa Physical Addresses 1114 | */ 1115 | extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); 1116 | 1117 | /*! Reads 32 bit value from a peripheral address WITHOUT the read barriers 1118 | You should only use this when: 1119 | o your code has previously called bcm2835_peri_read() for a register 1120 | within the same peripheral, and no read or write to another peripheral has occurred since. 1121 | o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. 1122 | 1123 | \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. 1124 | \return the value read from the 32 bit register 1125 | \sa Physical Addresses 1126 | */ 1127 | extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); 1128 | 1129 | 1130 | /*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write 1131 | This is safe, but slow. The MB before ensures that any in-flight write to another peripheral 1132 | completes before this write is issued. The MB after ensures that subsequent reads and writes 1133 | to another peripheral will see the effect of this write. 1134 | 1135 | This is a tricky optimization; if you aren't sure, use the barrier version. 1136 | 1137 | \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. 1138 | \param[in] value The 32 bit value to write 1139 | \sa Physical Addresses 1140 | */ 1141 | extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); 1142 | 1143 | /*! Writes 32 bit value from a peripheral address without the write barrier 1144 | You should only use this when: 1145 | o your code has previously called bcm2835_peri_write() for a register 1146 | within the same peripheral, and no other peripheral access has occurred since. 1147 | o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. 1148 | 1149 | This is a tricky optimization; if you aren't sure, use the barrier version. 1150 | 1151 | \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. 1152 | \param[in] value The 32 bit value to write 1153 | \sa Physical Addresses 1154 | */ 1155 | extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); 1156 | 1157 | /*! Alters a number of bits in a 32 peripheral regsiter. 1158 | It reads the current valu and then alters the bits defines as 1 in mask, 1159 | according to the bit value in value. 1160 | All other bits that are 0 in the mask are unaffected. 1161 | Use this to alter a subset of the bits in a register. 1162 | Memory barriers are used. Note that this is not atomic; an interrupt 1163 | routine can cause unexpected results. 1164 | \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. 1165 | \param[in] value The 32 bit value to write, masked in by mask. 1166 | \param[in] mask Bitmask that defines the bits that will be altered in the register. 1167 | \sa Physical Addresses 1168 | */ 1169 | extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); 1170 | /*! @} end of lowlevel */ 1171 | 1172 | /*! \defgroup gpio GPIO register access 1173 | These functions allow you to control the GPIO interface. You can set the 1174 | function of each GPIO pin, read the input state and set the output state. 1175 | @{ 1176 | */ 1177 | 1178 | /*! Sets the Function Select register for the given pin, which configures 1179 | the pin as Input, Output or one of the 6 alternate functions. 1180 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1181 | \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect 1182 | */ 1183 | extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); 1184 | 1185 | /*! Sets the specified pin output to 1186 | HIGH. 1187 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1188 | \sa bcm2835_gpio_write() 1189 | */ 1190 | extern void bcm2835_gpio_set(uint8_t pin); 1191 | 1192 | /*! Sets the specified pin output to 1193 | LOW. 1194 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1195 | \sa bcm2835_gpio_write() 1196 | */ 1197 | extern void bcm2835_gpio_clr(uint8_t pin); 1198 | 1199 | /*! Sets any of the first 32 GPIO output pins specified in the mask to 1200 | HIGH. 1201 | \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1202 | \sa bcm2835_gpio_write_multi() 1203 | */ 1204 | extern void bcm2835_gpio_set_multi(uint32_t mask); 1205 | 1206 | /*! Sets any of the first 32 GPIO output pins specified in the mask to 1207 | LOW. 1208 | \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1209 | \sa bcm2835_gpio_write_multi() 1210 | */ 1211 | extern void bcm2835_gpio_clr_multi(uint32_t mask); 1212 | 1213 | /*! Reads the current level on the specified 1214 | pin and returns either HIGH or LOW. Works whether or not the pin 1215 | is an input or an output. 1216 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1217 | \return the current level either HIGH or LOW 1218 | */ 1219 | extern uint8_t bcm2835_gpio_lev(uint8_t pin); 1220 | 1221 | /*! Event Detect Status. 1222 | Tests whether the specified pin has detected a level or edge 1223 | as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), 1224 | bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). 1225 | Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); 1226 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1227 | \return HIGH if the event detect status for the given pin is true. 1228 | */ 1229 | extern uint8_t bcm2835_gpio_eds(uint8_t pin); 1230 | 1231 | /*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in 1232 | the mask have detected a level or edge. 1233 | \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1234 | \return Mask of pins HIGH if the event detect status for the given pin is true. 1235 | */ 1236 | extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); 1237 | 1238 | /*! Sets the Event Detect Status register for a given pin to 1, 1239 | which has the effect of clearing the flag. Use this afer seeing 1240 | an Event Detect Status on the pin. 1241 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1242 | */ 1243 | extern void bcm2835_gpio_set_eds(uint8_t pin); 1244 | 1245 | /*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which 1246 | is set in the mask. 1247 | \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1248 | */ 1249 | extern void bcm2835_gpio_set_eds_multi(uint32_t mask); 1250 | 1251 | /*! Enable Rising Edge Detect Enable for the specified pin. 1252 | When a rising edge is detected, sets the appropriate pin in Event Detect Status. 1253 | The GPRENn registers use 1254 | synchronous edge detection. This means the input signal is sampled using the 1255 | system clock and then it is looking for a ?011? pattern on the sampled signal. This 1256 | has the effect of suppressing glitches. 1257 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1258 | */ 1259 | extern void bcm2835_gpio_ren(uint8_t pin); 1260 | 1261 | /*! Disable Rising Edge Detect Enable for the specified pin. 1262 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1263 | */ 1264 | extern void bcm2835_gpio_clr_ren(uint8_t pin); 1265 | 1266 | /*! Enable Falling Edge Detect Enable for the specified pin. 1267 | When a falling edge is detected, sets the appropriate pin in Event Detect Status. 1268 | The GPRENn registers use 1269 | synchronous edge detection. This means the input signal is sampled using the 1270 | system clock and then it is looking for a ?100? pattern on the sampled signal. This 1271 | has the effect of suppressing glitches. 1272 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1273 | */ 1274 | extern void bcm2835_gpio_fen(uint8_t pin); 1275 | 1276 | /*! Disable Falling Edge Detect Enable for the specified pin. 1277 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1278 | */ 1279 | extern void bcm2835_gpio_clr_fen(uint8_t pin); 1280 | 1281 | /*! Enable High Detect Enable for the specified pin. 1282 | When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. 1283 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1284 | */ 1285 | extern void bcm2835_gpio_hen(uint8_t pin); 1286 | 1287 | /*! Disable High Detect Enable for the specified pin. 1288 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1289 | */ 1290 | extern void bcm2835_gpio_clr_hen(uint8_t pin); 1291 | 1292 | /*! Enable Low Detect Enable for the specified pin. 1293 | When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. 1294 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1295 | */ 1296 | extern void bcm2835_gpio_len(uint8_t pin); 1297 | 1298 | /*! Disable Low Detect Enable for the specified pin. 1299 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1300 | */ 1301 | extern void bcm2835_gpio_clr_len(uint8_t pin); 1302 | 1303 | /*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. 1304 | When a rising edge is detected, sets the appropriate pin in Event Detect Status. 1305 | Asynchronous means the incoming signal is not sampled by the system clock. As such 1306 | rising edges of very short duration can be detected. 1307 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1308 | */ 1309 | extern void bcm2835_gpio_aren(uint8_t pin); 1310 | 1311 | /*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. 1312 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1313 | */ 1314 | extern void bcm2835_gpio_clr_aren(uint8_t pin); 1315 | 1316 | /*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. 1317 | When a falling edge is detected, sets the appropriate pin in Event Detect Status. 1318 | Asynchronous means the incoming signal is not sampled by the system clock. As such 1319 | falling edges of very short duration can be detected. 1320 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1321 | */ 1322 | extern void bcm2835_gpio_afen(uint8_t pin); 1323 | 1324 | /*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. 1325 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1326 | */ 1327 | extern void bcm2835_gpio_clr_afen(uint8_t pin); 1328 | 1329 | /*! Sets the Pull-up/down register for the given pin. This is 1330 | used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. 1331 | However, it is usually more convenient to use bcm2835_gpio_set_pud(). 1332 | \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl 1333 | \sa bcm2835_gpio_set_pud() 1334 | */ 1335 | extern void bcm2835_gpio_pud(uint8_t pud); 1336 | 1337 | /*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. 1338 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1339 | \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. 1340 | LOW to remove the clock. 1341 | \sa bcm2835_gpio_set_pud() 1342 | */ 1343 | extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); 1344 | 1345 | /*! Reads and returns the Pad Control for the given GPIO group. 1346 | Caution: requires root access. 1347 | \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* 1348 | \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup 1349 | */ 1350 | extern uint32_t bcm2835_gpio_pad(uint8_t group); 1351 | 1352 | /*! Sets the Pad Control for the given GPIO group. 1353 | Caution: requires root access. 1354 | \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* 1355 | \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note 1356 | that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this 1357 | is automatically included. 1358 | */ 1359 | extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); 1360 | 1361 | /*! Delays for the specified number of milliseconds. 1362 | Uses nanosleep(), and therefore does not use CPU until the time is up. 1363 | However, you are at the mercy of nanosleep(). From the manual for nanosleep(): 1364 | If the interval specified in req is not an exact multiple of the granularity 1365 | underlying clock (see time(7)), then the interval will be 1366 | rounded up to the next multiple. Furthermore, after the sleep completes, 1367 | there may still be a delay before the CPU becomes free to once 1368 | again execute the calling thread. 1369 | \param[in] millis Delay in milliseconds 1370 | */ 1371 | extern void bcm2835_delay (unsigned int millis); 1372 | 1373 | /*! Delays for the specified number of microseconds. 1374 | Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, 1375 | However, you are at the mercy of nanosleep(). From the manual for nanosleep(): 1376 | If the interval specified in req is not an exact multiple of the granularity 1377 | underlying clock (see time(7)), then the interval will be 1378 | rounded up to the next multiple. Furthermore, after the sleep completes, 1379 | there may still be a delay before the CPU becomes free to once 1380 | again execute the calling thread. 1381 | For times less than about 450 microseconds, uses a busy wait on the System Timer. 1382 | It is reported that a delay of 0 microseconds on RaspberryPi will in fact 1383 | result in a delay of about 80 microseconds. Your mileage may vary. 1384 | \param[in] micros Delay in microseconds 1385 | */ 1386 | extern void bcm2835_delayMicroseconds (uint64_t micros); 1387 | 1388 | /*! Sets the output state of the specified pin 1389 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1390 | \param[in] on HIGH sets the output to HIGH and LOW to LOW. 1391 | */ 1392 | extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); 1393 | 1394 | /*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on 1395 | \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1396 | \param[in] on HIGH sets the output to HIGH and LOW to LOW. 1397 | */ 1398 | extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); 1399 | 1400 | /*! Sets the first 32 GPIO output pins specified in the mask to the value given by value 1401 | \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1402 | \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) 1403 | */ 1404 | extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); 1405 | 1406 | /*! Sets the Pull-up/down mode for the specified pin. This is more convenient than 1407 | clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). 1408 | \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. 1409 | \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl 1410 | */ 1411 | extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); 1412 | 1413 | /*! @} */ 1414 | 1415 | /*! \defgroup spi SPI access 1416 | These functions let you use SPI0 (Serial Peripheral Interface) to 1417 | interface with an external SPI device. 1418 | @{ 1419 | */ 1420 | 1421 | /*! Start SPI operations. 1422 | Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) 1423 | to alternate function ALT0, which enables those pins for SPI interface. 1424 | You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to 1425 | their default functions. 1426 | \sa bcm2835_spi_end() 1427 | \return 1 if successful, 0 otherwise (perhaps because you are not running as root) 1428 | */ 1429 | extern int bcm2835_spi_begin(void); 1430 | 1431 | /*! End SPI operations. 1432 | SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) 1433 | are returned to their default INPUT behaviour. 1434 | */ 1435 | extern void bcm2835_spi_end(void); 1436 | 1437 | /*! Sets the SPI bit order 1438 | NOTE: has no effect. Not supported by SPI0. 1439 | Defaults to 1440 | \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, 1441 | see \ref bcm2835SPIBitOrder 1442 | */ 1443 | extern void bcm2835_spi_setBitOrder(uint8_t order); 1444 | 1445 | /*! Sets the SPI clock divider and therefore the 1446 | SPI clock speed. 1447 | \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, 1448 | see \ref bcm2835SPIClockDivider 1449 | */ 1450 | extern void bcm2835_spi_setClockDivider(uint16_t divider); 1451 | 1452 | /*! Sets the SPI data mode 1453 | Sets the clock polariy and phase 1454 | \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, 1455 | see \ref bcm2835SPIMode 1456 | */ 1457 | extern void bcm2835_spi_setDataMode(uint8_t mode); 1458 | 1459 | /*! Sets the chip select pin(s) 1460 | When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the 1461 | transfer. 1462 | \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. 1463 | One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect 1464 | */ 1465 | extern void bcm2835_spi_chipSelect(uint8_t cs); 1466 | 1467 | /*! Sets the chip select pin polarity for a given pin 1468 | When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) 1469 | will be asserted to the 1470 | value given by active. When transfers are not happening, the chip select pin(s) 1471 | return to the complement (inactive) value. 1472 | \param[in] cs The chip select pin to affect 1473 | \param[in] active Whether the chip select pin is to be active HIGH 1474 | */ 1475 | extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); 1476 | 1477 | /*! Transfers one byte to and from the currently selected SPI slave. 1478 | Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) 1479 | during the transfer. 1480 | Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. 1481 | Returns the read data byte from the slave. 1482 | Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual 1483 | \param[in] value The 8 bit data byte to write to MOSI 1484 | \return The 8 bit byte simultaneously read from MISO 1485 | \sa bcm2835_spi_transfern() 1486 | */ 1487 | extern uint8_t bcm2835_spi_transfer(uint8_t value); 1488 | 1489 | /*! Transfers any number of bytes to and from the currently selected SPI slave. 1490 | Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) 1491 | during the transfer. 1492 | Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. 1493 | The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long 1494 | Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual 1495 | \param[in] tbuf Buffer of bytes to send. 1496 | \param[out] rbuf Received bytes will by put in this buffer 1497 | \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received 1498 | \sa bcm2835_spi_transfer() 1499 | */ 1500 | extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); 1501 | 1502 | /*! Transfers any number of bytes to and from the currently selected SPI slave 1503 | using bcm2835_spi_transfernb. 1504 | The returned data from the slave replaces the transmitted data in the buffer. 1505 | \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents 1506 | \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received 1507 | \sa bcm2835_spi_transfer() 1508 | */ 1509 | extern void bcm2835_spi_transfern(char* buf, uint32_t len); 1510 | 1511 | /*! Transfers any number of bytes to the currently selected SPI slave. 1512 | Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) 1513 | during the transfer. 1514 | \param[in] buf Buffer of bytes to send. 1515 | \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send 1516 | */ 1517 | extern void bcm2835_spi_writenb(char* buf, uint32_t len); 1518 | 1519 | /*! @} */ 1520 | 1521 | /*! \defgroup i2c I2C access 1522 | These functions let you use I2C (The Broadcom Serial Control bus with the Philips 1523 | I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. 1524 | @{ 1525 | */ 1526 | 1527 | /*! Start I2C operations. 1528 | Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) 1529 | to alternate function ALT0, which enables those pins for I2C interface. 1530 | You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to 1531 | their default functions 1532 | \return 1 if successful, 0 otherwise (perhaps because you are not running as root) 1533 | \sa bcm2835_i2c_end() 1534 | */ 1535 | extern int bcm2835_i2c_begin(void); 1536 | 1537 | /*! End I2C operations. 1538 | I2C pins P1-03 (SDA) and P1-05 (SCL) 1539 | are returned to their default INPUT behaviour. 1540 | */ 1541 | extern void bcm2835_i2c_end(void); 1542 | 1543 | /*! Sets the I2C slave address. 1544 | \param[in] addr The I2C slave address. 1545 | */ 1546 | extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); 1547 | 1548 | /*! Sets the I2C clock divider and therefore the I2C clock speed. 1549 | \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, 1550 | see \ref bcm2835I2CClockDivider 1551 | */ 1552 | extern void bcm2835_i2c_setClockDivider(uint16_t divider); 1553 | 1554 | /*! Sets the I2C clock divider by converting the baudrate parameter to 1555 | the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) 1556 | For the I2C standard 100khz you would set baudrate to 100000 1557 | The use of baudrate corresponds to its use in the I2C kernel device 1558 | driver. (Of course, bcm2835 has nothing to do with the kernel driver) 1559 | */ 1560 | extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); 1561 | 1562 | /*! Transfers any number of bytes to the currently selected I2C slave. 1563 | (as previously set by \sa bcm2835_i2c_setSlaveAddress) 1564 | \param[in] buf Buffer of bytes to send. 1565 | \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. 1566 | \return reason see \ref bcm2835I2CReasonCodes 1567 | */ 1568 | extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); 1569 | 1570 | /*! Transfers any number of bytes from the currently selected I2C slave. 1571 | (as previously set by \sa bcm2835_i2c_setSlaveAddress) 1572 | \param[in] buf Buffer of bytes to receive. 1573 | \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. 1574 | \return reason see \ref bcm2835I2CReasonCodes 1575 | */ 1576 | extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); 1577 | 1578 | /*! Allows reading from I2C slaves that require a repeated start (without any prior stop) 1579 | to read after the required slave register has been set. For example, the popular 1580 | MPL3115A2 pressure and temperature sensor. Note that your device must support or 1581 | require this mode. If your device does not require this mode then the standard 1582 | combined: 1583 | \sa bcm2835_i2c_write 1584 | \sa bcm2835_i2c_read 1585 | are a better choice. 1586 | Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress 1587 | \param[in] regaddr Buffer containing the slave register you wish to read from. 1588 | \param[in] buf Buffer of bytes to receive. 1589 | \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. 1590 | \return reason see \ref bcm2835I2CReasonCodes 1591 | */ 1592 | extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); 1593 | 1594 | /*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated 1595 | start (with no prior stop) and reading a response. 1596 | Necessary for devices that require such behavior, such as the MLX90620. 1597 | Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress 1598 | \param[in] cmds Buffer containing the bytes to send before the repeated start condition. 1599 | \param[in] cmds_len Number of bytes to send from cmds buffer 1600 | \param[in] buf Buffer of bytes to receive. 1601 | \param[in] buf_len Number of bytes to receive in the buf buffer. 1602 | \return reason see \ref bcm2835I2CReasonCodes 1603 | */ 1604 | extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); 1605 | 1606 | /*! @} */ 1607 | 1608 | /*! \defgroup st System Timer access 1609 | Allows access to and delays using the System Timer Counter. 1610 | @{ 1611 | */ 1612 | 1613 | /*! Read the System Timer Counter register. 1614 | \return the value read from the System Timer Counter Lower 32 bits register 1615 | */ 1616 | extern uint64_t bcm2835_st_read(void); 1617 | 1618 | /*! Delays for the specified number of microseconds with offset. 1619 | \param[in] offset_micros Offset in microseconds 1620 | \param[in] micros Delay in microseconds 1621 | */ 1622 | extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); 1623 | 1624 | /*! @} */ 1625 | 1626 | /*! \defgroup pwm Pulse Width Modulation 1627 | Allows control of 2 independent PWM channels. A limited subset of GPIO pins 1628 | can be connected to one of these 2 channels, allowing PWM control of GPIO pins. 1629 | You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM 1630 | documentation on the Main Page. 1631 | @{ 1632 | */ 1633 | 1634 | /*! Sets the PWM clock divisor, 1635 | to control the basic PWM pulse widths. 1636 | \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common 1637 | values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider 1638 | */ 1639 | extern void bcm2835_pwm_set_clock(uint32_t divisor); 1640 | 1641 | /*! Sets the mode of the given PWM channel, 1642 | allowing you to control the PWM mode and enable/disable that channel 1643 | \param[in] channel The PWM channel. 0 or 1. 1644 | \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. 1645 | \param[in] enabled Set true to enable this channel and produce PWM pulses. 1646 | */ 1647 | extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); 1648 | 1649 | /*! Sets the maximum range of the PWM output. 1650 | The data value can vary between 0 and this range to control PWM output 1651 | \param[in] channel The PWM channel. 0 or 1. 1652 | \param[in] range The maximum value permitted for DATA. 1653 | */ 1654 | extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); 1655 | 1656 | /*! Sets the PWM pulse ratio to emit to DATA/RANGE, 1657 | where RANGE is set by bcm2835_pwm_set_range(). 1658 | \param[in] channel The PWM channel. 0 or 1. 1659 | \param[in] data Controls the PWM output ratio as a fraction of the range. 1660 | Can vary from 0 to RANGE. 1661 | */ 1662 | extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); 1663 | 1664 | /*! @} */ 1665 | #ifdef __cplusplus 1666 | } 1667 | #endif 1668 | 1669 | #endif /* BCM2835_H */ 1670 | 1671 | /*! @example blink.c 1672 | Blinks RPi GPIO pin 11 on and off 1673 | */ 1674 | 1675 | /*! @example input.c 1676 | Reads the state of an RPi input pin 1677 | */ 1678 | 1679 | /*! @example event.c 1680 | Shows how to use event detection on an input pin 1681 | */ 1682 | 1683 | /*! @example spi.c 1684 | Shows how to use SPI interface to transfer a byte to and from an SPI device 1685 | */ 1686 | 1687 | /*! @example spin.c 1688 | Shows how to use SPI interface to transfer a number of bytes to and from an SPI device 1689 | */ 1690 | 1691 | /*! @example pwm.c 1692 | Shows how to use PWM to control GPIO pins 1693 | */ 1694 | 1695 | /*! @example i2c.c 1696 | Command line utility for executing i2c commands with the 1697 | Broadcom bcm2835. Contributed by Shahrooz Shahparnia. 1698 | */ 1699 | 1700 | /*! example gpio.c 1701 | Command line utility for executing gpio commands with the 1702 | Broadcom bcm2835. Contributed by Shahrooz Shahparnia. 1703 | */ 1704 | -------------------------------------------------------------------------------- /examples/BCM2835/module.modulemap: -------------------------------------------------------------------------------- 1 | module BCM2835 [system] { 2 | header "bcm2835.h" 3 | link "bcm2835" 4 | export * 5 | } -------------------------------------------------------------------------------- /examples/Rakefile: -------------------------------------------------------------------------------- 1 | require_relative '../tooling/common.rb' 2 | 3 | task :default do 4 | system 'rake -T' 5 | end 6 | 7 | task :build do 8 | log 'Building' 9 | system_and_log 'clang blink_register.c -lbcm2835 -o blink' 10 | end 11 | 12 | task :run => :build do 13 | log 'Running' 14 | # system 'gcc -o blink blink_register.c -l bcm2835' 15 | system_and_log './blink' 16 | end 17 | 18 | desc 'Direct addressing example' 19 | task :direct do 20 | log 'Building' 21 | system_and_log 'clang direct_addressing.c -o direct' 22 | 23 | log 'Running' 24 | system_and_log 'sudo ./direct' 25 | end 26 | 27 | desc 'Swift direct memory example' 28 | task :swift do 29 | log 'Building' 30 | system_and_log 'swiftc directMemory.swift -o memory -Xlinker -lbcm2835 -L/usr/local/lib -v -Xlinker -v' 31 | 32 | log 'Running' 33 | system_and_log 'sudo ./memory' 34 | end -------------------------------------------------------------------------------- /examples/UnsafeMemory.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | var str = "Hello, playground" 6 | 7 | MemoryLayout.size // returns 8 (on 64-bit) 8 | MemoryLayout.alignment // returns 8 (on 64-bit) 9 | MemoryLayout.stride // returns 8 (on 64-bit) 10 | 11 | MemoryLayout.size // returns 2 12 | MemoryLayout.alignment // returns 2 13 | MemoryLayout.stride // returns 2 14 | 15 | MemoryLayout.size // returns 1 16 | MemoryLayout.alignment // returns 1 17 | MemoryLayout.stride // returns 1 18 | 19 | struct SampleStruct { 20 | let number: UInt32 21 | let flag: Bool 22 | } 23 | 24 | MemoryLayout.size // returns 5 25 | MemoryLayout.alignment // returns 4 26 | MemoryLayout.stride // returns 8 27 | 28 | // 1 29 | let count = 2 30 | let stride = MemoryLayout.stride 31 | let alignment = MemoryLayout.alignment 32 | let byteCount = stride * count 33 | 34 | // 2 35 | do { 36 | print("Raw pointers") 37 | 38 | // 3 39 | let pointer = UnsafeMutableRawPointer.allocate(bytes: byteCount, alignedTo: alignment) 40 | // 4 41 | defer { 42 | pointer.deallocate(bytes: byteCount, alignedTo: alignment) 43 | } 44 | 45 | // 5 46 | pointer.storeBytes(of: 42, as: Int.self) 47 | pointer.advanced(by: stride).storeBytes(of: 6, as: Int.self) 48 | pointer.load(as: Int.self) 49 | pointer.advanced(by: stride).load(as: Int.self) 50 | 51 | // 6 52 | let bufferPointer = UnsafeRawBufferPointer(start: pointer, count: byteCount) 53 | for (index, byte) in bufferPointer.enumerated() { 54 | print("byte \(index): \(byte)") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/UnsafeMemory.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/UnsafeMemory.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/UnsafeMemory.playground/playground.xcworkspace/xcuserdata/steven_hepting.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/UnsafeMemory.playground/playground.xcworkspace/xcuserdata/steven_hepting.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /examples/blink: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/blink -------------------------------------------------------------------------------- /examples/blink_register.c: -------------------------------------------------------------------------------- 1 | // 2 | // blink_register.c 3 | // 4 | 5 | #include 6 | #include 7 | 8 | int main(int argc, char **argv) { 9 | if (!bcm2835_init()) { 10 | return 1; 11 | } 12 | 13 | bcm2835_gpio_fsel(RPI_GPIO_P1_07, BCM2835_GPIO_FSEL_OUTP); 14 | while (1) { 15 | printf("On.\n"); 16 | bcm2835_gpio_write(RPI_GPIO_P1_07, HIGH); 17 | bcm2835_delay(500); 18 | printf("Off.\n"); 19 | bcm2835_gpio_write(RPI_GPIO_P1_07, LOW); 20 | bcm2835_delay(500); 21 | } 22 | bcm2835_close(); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /examples/direct: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/direct -------------------------------------------------------------------------------- /examples/directMemory.swift: -------------------------------------------------------------------------------- 1 | #!/usr/bin/swift 2 | 3 | import Foundation // for String(format, ) 4 | import Glibc // for mmap 5 | 6 | func loopGPIO() { 7 | let file = open("/dev/mem", O_RDWR | O_SYNC); 8 | defer { close(file) } 9 | 10 | // Open the /dev/mem file (all memory) with read and write 11 | // privileges (we want to turn on output pins) at the proper 12 | // offset (we don't care about the rest of the addresses) 13 | // 0x3f200000 14 | guard let rawPointer = mmap(nil, 1024 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, file, 0x3f200000) else { 15 | perror("Cannot mmap bytes for path") 16 | return 17 | } 18 | // This is a typed pointer to the root of the GPIO configuration 19 | // registers. Pointer math will increment by 4 bytes at a time. 20 | let basePointer: UnsafeMutablePointer = rawPointer.bindMemory(to: UInt32.self, capacity: 30) 21 | 22 | // Configure GPIO pin 4 & 6 as output (3 bits/pin) 23 | // pin numbers: 8 7 6 5 4 3 2 1 0 24 | // basePointer.pointee = 0b000001001000000000000000 25 | 26 | 27 | guard let rawPointer2 = mmap(nil, 1024 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, file, 0x3f200000) else { 28 | perror("Cannot mmap bytes for path") 29 | return 30 | } 31 | // let basePointer2: UnsafeMutabl ePointer = rawPointer2.bindMemory(to: UInt32.self, capacity: 30) 32 | 33 | // pin numbers: 22 21 20 19 18 17 16 15 14 13 12 11 // 10 9 8 7 6 5 4 3 2 1 0 34 | // basePointer2.pointee = 0b00001000000000000000000000000000 //000000000000001001000000000000000 35 | 36 | // Set up set/clear pointer objects 37 | // Offsets from docs were given in byte-size values 38 | // since our pointers are smart and expecting word 39 | // size values we convert 40 | let setPointer = basePointer + 0x1C/4 41 | let clearPointer = basePointer + 0x28/4 42 | 43 | // Print the details for sanity sake 44 | print("Configuration Details") 45 | print(" address: \(basePointer)") 46 | print(String(format: " format: 0x%X", basePointer.pointee)) 47 | 48 | print("Set pointer: \(setPointer)") 49 | print("Clear pointer: \(clearPointer)") 50 | 51 | // Loop through and show the LED turning on and off 52 | for i in 0...5 { 53 | print("High \(setPointer)") 54 | setPointer.pointee = 0b100000100000000000001100000 // Pin 20, 6 & 5 55 | usleep(500000) 56 | print("Counter: \(i)") 57 | print("Low \(clearPointer)") 58 | clearPointer.pointee = 0b100000100000000000001100000 // Pin 20, 6 & 5 59 | usleep(500000) 60 | } 61 | } 62 | 63 | loopGPIO() -------------------------------------------------------------------------------- /examples/direct_addressing.c: -------------------------------------------------------------------------------- 1 | // 2 | // direct_addressing.c 3 | // 4 | 5 | #include 6 | #include 7 | // #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef unsigned int uint32_t; 15 | 16 | int main(int argc, char** argv) { 17 | // Load the memory addresses into this process address space 18 | // as a memory-mapped 'file' 19 | int memfd = open("/dev/mem", O_RDWR | O_SYNC); 20 | uint32_t * map = (uint32_t *)mmap( 21 | NULL, 22 | 1024 * 4, 23 | (PROT_READ | PROT_WRITE), 24 | MAP_SHARED, 25 | memfd, 26 | 0x3f200000); 27 | if (map == MAP_FAILED) { 28 | printf("bcm2835_init - mmap failed: %s\n", strerror(errno)); 29 | } 30 | close(memfd); 31 | 32 | printf("Setting up pointers.\n"); 33 | // Set output type 34 | volatile uint32_t* paddr = map; 35 | *paddr = 0x1000; 36 | printf("Base pointer: %p\n", paddr); 37 | 38 | // Switch from high to low as fast as possible 39 | volatile uint32_t* paddr1 = map + 0x1C/4; 40 | printf("Set register %p.\n", paddr1); 41 | 42 | volatile uint32_t* paddr2 = map + 0x28/4; 43 | printf("Clear register %p.\n", paddr2); 44 | uint32_t mask = 0x10; 45 | for (int i = 0; i < 5; i++) 46 | { 47 | printf("High %p \n", paddr1); 48 | *paddr1 = mask; // Set 49 | usleep(500000); 50 | printf("Low %p.\n", paddr2); 51 | *paddr2 = mask; // Clear 52 | usleep(500000); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/direct_old: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/direct_old -------------------------------------------------------------------------------- /examples/failed/sht30/SHT30: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/failed/sht30/SHT30 -------------------------------------------------------------------------------- /examples/failed/sht30/sht30.c: -------------------------------------------------------------------------------- 1 | // Distributed with a free-will license. 2 | // Use it any way you want, profit or free, provided it fits in the licenses of its associated works. 3 | // SHT30 4 | // This code is designed to work with the SHT30_I2CS I2C Mini Module available from ControlEverything.com. 5 | // https://www.controleverything.com/content/Humidity?sku=SHT30_I2CS#tabs-0-product_tabset-2 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void main() 14 | { 15 | // Create I2C bus 16 | int file; 17 | char *bus = "/dev/i2c-1"; 18 | if ((file = open(bus, O_RDWR)) < 0) 19 | { 20 | printf("Failed to open the bus. \n"); 21 | exit(1); 22 | } 23 | // Get I2C device, SHT30 I2C address is 0x44(68) 24 | ioctl(file, I2C_SLAVE, 0x45); 25 | 26 | // Send measurement command(0x2C) 27 | // High repeatability measurement(0x06) 28 | int command = 0x2c06; 29 | 30 | char config[2] = {0}; 31 | // config[0] = 0x2C; // Clock stretching 32 | config[0] = (command >> 8) & 0xff; 33 | config[1] = command & 0xff; 34 | printf("Command 0: 0x%02x\n", config[0]); 35 | printf("Command 1: 0x%02x\n", config[1]); 36 | 37 | write(file, config, 2); 38 | // usleep(5000); 39 | sleep(1); 40 | 41 | // Read 6 bytes of data 42 | // Temp msb, Temp lsb, Temp CRC, Humididty msb, Humidity lsb, Humidity CRC 43 | char data[6] = {0}; 44 | if(read(file, data, 6) != 6) 45 | { 46 | printf("Error : Input/output Error \n"); 47 | } 48 | else 49 | { 50 | // Convert the data 51 | int temp = (data[0] << 8 | data[1]); 52 | printf("Field 1: 0x%02x\n", data[0]); 53 | printf("Field 2: 0x%02x\n", data[1]); 54 | printf("Field 3: 0x%02x\n", data[2]); 55 | printf("Field 4: 0x%02x\n", data[3]); 56 | printf("Field 5: 0x%02x\n", data[4]); 57 | printf("Field 6: 0x%02x\n", data[5]); 58 | 59 | printf("Temp: %i\n", temp); 60 | // int temp = (data[1] * 256 + data[0]); 61 | 62 | float cTemp = -45 + (175 * temp / 65535.0); 63 | float fTemp = -49 + (315 * temp / 65535.0); 64 | float humidity = 100 * (data[3] * 256 + data[4]) / 65535.0; 65 | 66 | // Output data to screen 67 | printf("Relative Humidity : %.2f RH \n", humidity); 68 | printf("Temperature in Celsius : %.2f C \n", cTemp); 69 | printf("Temperature in Fahrenheit : %.2f F \n", fTemp); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /examples/failed/sht30/sht30.py: -------------------------------------------------------------------------------- 1 | # Distributed with a free-will license. 2 | # Use it any way you want, profit or free, provided it fits in the licenses of its associated works. 3 | # SHT31 4 | # This code is designed to work with the SHT31_I2CS I2C Mini Module available from ControlEverything.com. 5 | # https://www.controleverything.com/content/Humidity?sku=SHT31_I2CS#tabs-0-product_tabset-2 6 | 7 | import smbus 8 | import time 9 | 10 | # Get I2C bus 11 | bus = smbus.SMBus(1) 12 | 13 | # SHT31 address, 0x44(68) 14 | # Send measurement command, 0x2C(44) 15 | # 0x06(06) High repeatability measurement 16 | bus.write_i2c_block_data(0x45, 0x2C, [0x06]) 17 | 18 | time.sleep(0.5) 19 | 20 | # SHT31 address, 0x44(68) 21 | # Read data back from 0x00(00), 6 bytes 22 | # Temp MSB, Temp LSB, Temp CRC, Humididty MSB, Humidity LSB, Humidity CRC 23 | data = bus.read_i2c_block_data(0x45, 0x00, 6) 24 | 25 | # Convert the data 26 | temp = data[0] * 256 + data[1] 27 | cTemp = -45 + (175 * temp / 65535.0) 28 | fTemp = -49 + (315 * temp / 65535.0) 29 | humidity = 100 * (data[3] * 256 + data[4]) / 65535.0 30 | 31 | # Output data to screen 32 | print "Temperature in Celsius is : %.2f C" %cTemp 33 | print "Temperature in Fahrenheit is : %.2f F" %fTemp 34 | print "Relative Humidity is : %.2f %%RH" %humidity 35 | -------------------------------------------------------------------------------- /examples/failed/sht30/sht3xd.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @section License 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017, Google Inc. 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, copy, 12 | * modify, merge, publish, distribute, sublicense, and/or sell copies 13 | * of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | * This code was originally written by Simon L. B. Nielsen. 29 | * 30 | * This file is part of the Simba project. 31 | */ 32 | 33 | #include "simba.h" 34 | 35 | /* 36 | * This driver supports the Sensirion SHT3x-D series of digital of 37 | * Humidity and Temperature Sensors, specifically the SHT30-D, 38 | * SHT31-D, and SHT35-D. 39 | * 40 | * Datasheet: 41 | * https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf 42 | * 43 | * Reference code: 44 | * https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/11_Sample_Codes_Software/Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Sample_Code_V2.pdf 45 | */ 46 | 47 | #if CONFIG_SHT3XD == 1 48 | 49 | #define CMD_SINGLE_CLKSTRETCH_REPHIGH 0x2c06 50 | #define CMD_SINGLE_NOCLKSTRETCH_REPHIGH 0x2400 51 | #define CMD_GETSERIAL 0x3780 52 | 53 | #ifdef CONFIG_SHT3XD_DEBUG_LOG_MASK 54 | # define DLOG(self_p, level, msg, ...) \ 55 | log_object_print(&(self_p)->log, level, OSTR(msg), ##__VA_ARGS__) 56 | #else 57 | # define DLOG(self_p, level, msg, ...) 58 | #endif 59 | 60 | /** 61 | * Send a single 16bit command to the SHT3x-D device. 62 | */ 63 | static int sht3xd_sendcmd(struct sht3xd_driver_t *self_p, uint16_t cmd) 64 | { 65 | uint8_t i2ccmd[2]; 66 | int res; 67 | 68 | i2ccmd[0] = (cmd >> 8) & 0xff; 69 | i2ccmd[1] = cmd & 0xff; 70 | DLOG(self_p, LOG_DEBUG, "Sending command 0x%04x to device", cmd); 71 | res = i2c_soft_write(self_p->i2c_p, self_p->i2c_addr, i2ccmd, 2); 72 | 73 | if (res != 2) { 74 | DLOG(self_p, LOG_ERROR, "Failed to write to device: %d", res); 75 | 76 | if (res < 0) { 77 | return (res); 78 | } 79 | 80 | return (-EIO); 81 | } 82 | 83 | return (0); 84 | } 85 | 86 | /** 87 | * Read 2x 16bit to the SHT3x-D device. 88 | */ 89 | static int sht3xd_read2x16(struct sht3xd_driver_t *self_p, uint8_t *data_p) 90 | { 91 | int res; 92 | 93 | res = i2c_soft_read(self_p->i2c_p, self_p->i2c_addr, data_p, 6); 94 | 95 | if (res != 6) { 96 | DLOG(self_p, LOG_ERROR, "Failed to read data: %d", res); 97 | return (-EIO); 98 | } 99 | 100 | DLOG(self_p, 101 | LOG_DEBUG, 102 | "Got data from SHT3x: 0x%02x%02x%02x 0x%02x%02x%02x", 103 | data_p[0], 104 | data_p[1], 105 | data_p[2], 106 | data_p[3], 107 | data_p[4], 108 | data_p[5]); 109 | 110 | // Here should go CRC check. 111 | 112 | return (0); 113 | } 114 | 115 | /** 116 | * Read serial off SHT3x-D. 117 | */ 118 | static int sht3xd_read_serial(struct sht3xd_driver_t *self_p) 119 | { 120 | int res; 121 | uint8_t data[6]; 122 | 123 | res = sht3xd_sendcmd(self_p, CMD_GETSERIAL); 124 | 125 | if (res != 0) { 126 | return (res); 127 | } 128 | 129 | res = sht3xd_read2x16(self_p, data); 130 | 131 | if (res != 0) { 132 | return (res); 133 | } 134 | 135 | self_p->serial = data[0] << 24 | data[1] << 16 | data[3] << 8 | data[4]; 136 | 137 | return (0); 138 | } 139 | 140 | int sht3xd_module_init() 141 | { 142 | i2c_soft_module_init(); 143 | #ifdef CONFIG_SHT3XD_DEBUG_LOG_MASK 144 | log_module_init(); 145 | #endif 146 | 147 | return (0); 148 | } 149 | 150 | int sht3xd_init(struct sht3xd_driver_t *self_p, 151 | struct i2c_soft_driver_t *i2c_p, 152 | int i2c_addr) 153 | { 154 | ASSERTN(self_p != NULL, EINVAL); 155 | ASSERTN(i2c_p != NULL, EINVAL); 156 | 157 | self_p->i2c_p = i2c_p; 158 | self_p->i2c_addr = i2c_addr; 159 | 160 | #ifdef CONFIG_SHT3XD_DEBUG_LOG_MASK 161 | log_object_init(&self_p->log, "sht3xd", CONFIG_SHT3XD_DEBUG_LOG_MASK); 162 | #endif 163 | 164 | return (0); 165 | } 166 | 167 | int sht3xd_start(struct sht3xd_driver_t *self_p) 168 | { 169 | ASSERTN(self_p != NULL, EINVAL); 170 | 171 | int res; 172 | 173 | DLOG(self_p, LOG_INFO, "Starting SHT3x-D driver"); 174 | i2c_soft_start(self_p->i2c_p); 175 | 176 | if (i2c_soft_scan(self_p->i2c_p, self_p->i2c_addr) != 1) { 177 | DLOG(self_p, LOG_WARNING, "No device found at 0x%x", self_p->i2c_addr); 178 | return (-ENOENT); 179 | } 180 | 181 | res = sht3xd_read_serial(self_p); 182 | 183 | if (res != 0) { 184 | DLOG(self_p, 185 | LOG_ERROR, 186 | "Error reading serial from 0x%x", 187 | self_p->i2c_addr); 188 | return (res); 189 | } 190 | 191 | DLOG(self_p, 192 | LOG_INFO, 193 | "Device found serial %8x at 0x%x", 194 | self_p->serial, 195 | self_p->i2c_addr); 196 | 197 | return (0); 198 | } 199 | 200 | /** 201 | * Calculate the temperature in Celsius from SHT3xD raw temperature. 202 | */ 203 | static float sht3xd_calculate_temp_c(uint8_t msb, uint8_t lsb) 204 | { 205 | uint16_t val; 206 | float temp; 207 | 208 | val = msb << 8 | lsb; 209 | temp = 175.0f * ((float)val / 65535.0f) - 45.0f; 210 | 211 | return (temp); 212 | } 213 | 214 | /** 215 | * Calculate the humidity from SHT3xD raw temperature. 216 | */ 217 | static float sht3xd_calculate_humid(uint8_t msb, uint8_t lsb) 218 | { 219 | uint16_t val; 220 | float humid; 221 | 222 | val = msb << 8 | lsb; 223 | humid = 100.0f * ((float)val / 65535.0f); 224 | 225 | return (humid); 226 | } 227 | 228 | int sht3xd_get_temp_humid(struct sht3xd_driver_t *self_p, 229 | float *temp_p, 230 | float *humid_p) 231 | { 232 | ASSERTN(self_p != NULL, EINVAL); 233 | 234 | int res; 235 | uint8_t data[6]; 236 | 237 | /* 238 | * We use a non-clockstreching command followed by a sleep and 239 | * then issue read of the result. This is so we can do a single 240 | * long sleep (probably a bit more power efficient), and to not 241 | * block the I2C bus while sensor is active - in case it's shared. 242 | */ 243 | res = sht3xd_sendcmd(self_p, CMD_SINGLE_NOCLKSTRETCH_REPHIGH); 244 | 245 | if (res != 0) { 246 | return (res); 247 | } 248 | 249 | // We use max duration to avoid having to handle retry. 250 | thrd_sleep_ms(MEASUREMENT_DURATION_HIGH_MS); 251 | 252 | res = sht3xd_read2x16(self_p, data); 253 | 254 | if (res != 0) { 255 | return (res); 256 | } 257 | 258 | if (temp_p != NULL) { 259 | *temp_p = sht3xd_calculate_temp_c(data[0], data[1]); 260 | } 261 | if (humid_p != NULL) { 262 | *humid_p = sht3xd_calculate_humid(data[3], data[4]); 263 | } 264 | 265 | return (0); 266 | } 267 | 268 | int sht3xd_get_serial(struct sht3xd_driver_t *self_p, 269 | uint32_t *serial_p) 270 | { 271 | ASSERTN(self_p != NULL, EINVAL); 272 | ASSERTN(serial != NULL, EINVAL); 273 | 274 | *serial_p = self_p->serial; 275 | 276 | return (0); 277 | } 278 | 279 | #endif 280 | -------------------------------------------------------------------------------- /examples/failed/temp_c/dht: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/failed/temp_c/dht -------------------------------------------------------------------------------- /examples/failed/temp_c/dht.c: -------------------------------------------------------------------------------- 1 | /* 2 | * dht.c: 3 | * read temperature and humidity from DHT11 or DHT22 sensor 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_TIMINGS 85 12 | #define DHT_PIN 3 /* GPIO-22 */ 13 | 14 | int data[5] = { 0, 0, 0, 0, 0 }; 15 | 16 | void read_dht_data() 17 | { 18 | uint8_t laststate = HIGH; 19 | uint8_t counter = 0; 20 | uint8_t j = 0, i; 21 | 22 | data[0] = data[1] = data[2] = data[3] = data[4] = 0; 23 | 24 | /* pull pin down for 18 milliseconds */ 25 | pinMode( DHT_PIN, OUTPUT ); 26 | digitalWrite( DHT_PIN, LOW ); 27 | delay( 18 ); 28 | 29 | /* prepare to read the pin */ 30 | pinMode( DHT_PIN, INPUT ); 31 | 32 | /* detect change and read data */ 33 | for ( i = 0; i < MAX_TIMINGS; i++ ) 34 | { 35 | counter = 0; 36 | while ( digitalRead( DHT_PIN ) == laststate ) 37 | { 38 | counter++; 39 | delayMicroseconds( 1 ); 40 | if ( counter == 255 ) 41 | { 42 | break; 43 | } 44 | } 45 | laststate = digitalRead( DHT_PIN ); 46 | 47 | if ( counter == 255 ) 48 | break; 49 | 50 | /* ignore first 3 transitions */ 51 | if ( (i >= 4) && (i % 2 == 0) ) 52 | { 53 | /* shove each bit into the storage bytes */ 54 | data[j / 8] <<= 1; 55 | if ( counter > 16 ) 56 | data[j / 8] |= 1; 57 | j++; 58 | } 59 | } 60 | 61 | /* 62 | * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte 63 | * print it out if data is good 64 | */ 65 | if ( (j >= 40) && 66 | (data[4] == ( (data[0] + data[1] + data[2] + data[3]) & 0xFF) ) ) 67 | { 68 | float h = (float)((data[0] << 8) + data[1]) / 10; 69 | if ( h > 100 ) 70 | { 71 | h = data[0]; // for DHT11 72 | } 73 | float c = (float)(((data[2] & 0x7F) << 8) + data[3]) / 10; 74 | if ( c > 125 ) 75 | { 76 | c = data[2]; // for DHT11 77 | } 78 | if ( data[2] & 0x80 ) 79 | { 80 | c = -c; 81 | } 82 | float f = c * 1.8f + 32; 83 | printf( "Humidity = %.1f %% Temperature = %.1f *C (%.1f *F)\n", h, c, f ); 84 | }else { 85 | printf( "Data not good, skip\n" ); 86 | } 87 | } 88 | 89 | int main( void ) 90 | { 91 | printf( "Raspberry Pi DHT11/DHT22 temperature/humidity test\n" ); 92 | 93 | if ( wiringPiSetup() == -1 ) 94 | exit( 1 ); 95 | 96 | while ( 1 ) 97 | { 98 | read_dht_data(); 99 | delay( 2000 ); /* wait 2 seconds before next read */ 100 | } 101 | 102 | return(0); 103 | } 104 | 105 | -------------------------------------------------------------------------------- /examples/failed/temp_c/dht.py: -------------------------------------------------------------------------------- 1 | import RPi.GPIO as GPIO 2 | import time 3 | import sys 4 | 5 | def bin2dec(string_num): 6 | return str(int(string_num, 2)) 7 | 8 | data = [] 9 | 10 | GPIO.setmode(GPIO.BCM) 11 | 12 | GPIO.setup(4,GPIO.OUT) 13 | GPIO.output(4,GPIO.HIGH) 14 | time.sleep(0.025) 15 | GPIO.output(4,GPIO.LOW) 16 | time.sleep(0.02) 17 | 18 | GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP) 19 | 20 | for i in range(0,500): 21 | data.append(GPIO.input(4)) 22 | 23 | bit_count = 0 24 | tmp = 0 25 | count = 0 26 | HumidityBit = "" 27 | TemperatureBit = "" 28 | crc = "" 29 | 30 | try: 31 | while data[count] == 1: 32 | tmp = 1 33 | count = count + 1 34 | 35 | for i in range(0, 32): 36 | bit_count = 0 37 | 38 | while data[count] == 0: 39 | tmp = 1 40 | count = count + 1 41 | 42 | while data[count] == 1: 43 | bit_count = bit_count + 1 44 | count = count + 1 45 | 46 | if bit_count > 3: 47 | if i>=0 and i<8: 48 | HumidityBit = HumidityBit + "1" 49 | if i>=16 and i<24: 50 | TemperatureBit = TemperatureBit + "1" 51 | else: 52 | if i>=0 and i<8: 53 | HumidityBit = HumidityBit + "0" 54 | if i>=16 and i<24: 55 | TemperatureBit = TemperatureBit + "0" 56 | 57 | except Exception as e: 58 | print "ERR_RANGE 1" 59 | print "Error({0})".format(e) 60 | print "Unexpected error", sys.exc_info()[0] 61 | exit(0) 62 | 63 | try: 64 | for i in range(0, 8): 65 | bit_count = 0 66 | 67 | while data[count] == 0: 68 | tmp = 1 69 | count = count + 1 70 | 71 | while data[count] == 1: 72 | bit_count = bit_count + 1 73 | count = count + 1 74 | 75 | if bit_count > 3: 76 | crc = crc + "1" 77 | else: 78 | crc = crc + "0" 79 | except: 80 | print "ERR_RANGE 2" 81 | exit(0) 82 | 83 | Humidity = bin2dec(HumidityBit) 84 | Temperature = bin2dec(TemperatureBit) 85 | 86 | if int(Humidity) + int(Temperature) - int(bin2dec(crc)) == 0: 87 | print "Humidity:"+ Humidity +"%" 88 | print "Temperature:"+ Temperature +"C" 89 | else: 90 | print "ERR_CRC" 91 | 92 | -------------------------------------------------------------------------------- /examples/failed/temp_c/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | gcc dht.c -o dht -lwiringPi 4 | sudo ./dht 5 | -------------------------------------------------------------------------------- /examples/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/hello -------------------------------------------------------------------------------- /examples/hello.swift: -------------------------------------------------------------------------------- 1 | print("Hello Swift Summit") 2 | -------------------------------------------------------------------------------- /examples/memory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/memory -------------------------------------------------------------------------------- /examples/random.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shepting/raspberry-swift/a5cfadcba5e420f9c3a1706b9b22326877ed0806/examples/random.dat -------------------------------------------------------------------------------- /source/Package.pins: -------------------------------------------------------------------------------- 1 | { 2 | "autoPin": true, 3 | "pins": [ 4 | { 5 | "package": "DS18B20", 6 | "reason": null, 7 | "repositoryURL": "https://github.com/uraimo/DS18B20.swift.git", 8 | "version": "1.0.3" 9 | }, 10 | { 11 | "package": "SwiftyGPIO", 12 | "reason": null, 13 | "repositoryURL": "https://github.com/uraimo/SwiftyGPIO.git", 14 | "version": "0.9.11" 15 | } 16 | ], 17 | "version": 1 18 | } -------------------------------------------------------------------------------- /source/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "SwiftyGPIO", 6 | "repositoryURL": "https://github.com/uraimo/SwiftyGPIO.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "34022e469925ea640b41afe3599871fc0ab57ab3", 10 | "version": "0.9.11" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /source/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:3.1 2 | 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "RaspberrySwift", 8 | targets: [ 9 | Target( 10 | name: "RaspberrySwift", 11 | dependencies: ["Home"] 12 | ), 13 | Target(name: "Home") 14 | ], 15 | dependencies: [ 16 | .Package(url: "https://github.com/uraimo/SwiftyGPIO.git", majorVersion: 0), 17 | .Package(url: "https://github.com/uraimo/DS18B20.swift.git", majorVersion: 1), 18 | ] 19 | ) 20 | -------------------------------------------------------------------------------- /source/Rakefile: -------------------------------------------------------------------------------- 1 | 2 | require_relative '../tooling/swift_build.rb' 3 | require_relative '../tooling/common.rb' 4 | 5 | 6 | task :default do 7 | system 'rake --tasks' 8 | end 9 | 10 | desc 'Build the project' 11 | task :build do 12 | log 'Building project' 13 | system_and_log 'swift build' 14 | end 15 | 16 | desc 'Build and run the project using Swift PM' 17 | task run: :build do 18 | log 'Running project' 19 | system_and_log '.build/debug/RaspberrySwift' 20 | end 21 | 22 | desc 'Build on Linux' 23 | task :linux do 24 | log 'Building individual' 25 | build_individual 26 | end 27 | 28 | # Logging to Amazon Cloudwatch 29 | namespace :log do 30 | desc 'Log the processor temperature to Cloudwatch' 31 | task :processor_temp do 32 | log 'Logging CPU temp' 33 | system_and_log 'aws cloudwatch put-metric-data --metric-name ProcessorTemperatureCelcius --namespace RaspberrySwift --unit Count --value $(expr `cat /sys/class/thermal/thermal_zone0/temp` / 1000)' 34 | end 35 | 36 | desc 'Log the GPU temperature to Cloudwatch' 37 | task :gpu_temp do 38 | require 'open3' 39 | temp_string, success = Open3.capture2e('/opt/vc/bin/vcgencmd', 'measure_temp') 40 | temp_value = temp_string.match(/=(.*)'/)[1] 41 | command = 'aws cloudwatch put-metric-data --metric-name GPUTemperatureCelcius --namespace RaspberrySwift --unit Count --value ' + temp_value 42 | system_and_log command 43 | end 44 | 45 | desc 'Log boot event to Cloudwatch' 46 | task :boot do 47 | system_and_log 'aws cloudwatch put-metric-data --metric-name Boot --namespace RaspberrySwift --unit Count --value 1' 48 | end 49 | end 50 | 51 | namespace :view do 52 | desc 'View the crontab log' 53 | task :crontab_log do 54 | system_and_log 'grep CRON /var/log/syslog' 55 | end 56 | 57 | desc 'View memory offsets' 58 | task :memory_offsets do 59 | system_and_log 'cat /proc/iomem' 60 | end 61 | end 62 | 63 | task :i2c do 64 | build_with_module 65 | 66 | # Execute the executable. 67 | # system 'DYLD_LIBRARY_PATH=foo-out ./main-out/Main' 68 | end 69 | -------------------------------------------------------------------------------- /source/Sources/Home/AnalogReader.swift: -------------------------------------------------------------------------------- 1 | 2 | import Foundation 3 | import SwiftyGPIO 4 | import DS18B20 5 | 6 | func shortSleep() { 7 | usleep(100000) 8 | } 9 | 10 | public struct AnalogReader { 11 | let ds: DS18B20 12 | public init() { 13 | let onewires = SwiftyGPIO.hardware1Wires(for:.RaspberryPi3)! 14 | print("One wires: \(onewires)") 15 | let onewire = onewires[0] 16 | // let slaveId = onewire.getSlaves()[] 17 | print("Slaves: \(onewire.getSlaves())") 18 | ds = DS18B20(onewire, slaveId: "28-0000097eb360") 19 | // GPIO16 20 | } 21 | 22 | public func readValue() -> Float { 23 | return ds.Temperature 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /source/Sources/Home/DataStore.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class DataStore { 4 | var data = [Date: Float]() 5 | 6 | func saveValue(_ value: Float) { 7 | let date = Date() 8 | data[date] = value 9 | print(data) 10 | } 11 | 12 | func writeData() { 13 | let bundle = Bundle(for: DataStore.self) 14 | let bundleURL = bundle.bundleURL 15 | if #available(OSX 10.11, *) { 16 | let dataLogURL = URL(fileURLWithPath: "data.plist", relativeTo:bundleURL) 17 | print(dataLogURL) 18 | print(dataLogURL.path) 19 | 20 | let data_copy = data //as NSDictionary 21 | print(data_copy) 22 | //data_copy.write(to: dataLogURL, atomically: true) 23 | 24 | } 25 | // print(Bundle()) 26 | // print(Bundle.allBundles) 27 | // let url = Bundle.main 28 | // print(url) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /source/Sources/Home/LightSwitch.swift: -------------------------------------------------------------------------------- 1 | import SwiftyGPIO 2 | 3 | public struct LightSwitch { 4 | let ledPin: GPIO // LED 5 | let relayPin: GPIO // Relay 6 | 7 | public init?() { 8 | // Create the pins 9 | let gpios = SwiftyGPIO.GPIOs(for:.RaspberryPi3) 10 | guard let ledPin = gpios[.P5] else { print("Invalid GPIO: .P5"); return nil } 11 | guard let relayPin = gpios[.P6] else { print("Invalid GPIO: .P6"); return nil } 12 | self.ledPin = ledPin 13 | self.relayPin = relayPin 14 | 15 | // Set the pins to be outputs 16 | ledPin.direction = .OUT 17 | relayPin.direction = .OUT 18 | } 19 | 20 | // Turn all of the pins on 21 | public func on() { 22 | print("🌕 On") 23 | ledPin.value = 1 24 | relayPin.value = 1 25 | } 26 | 27 | // Turn all of the pins off 28 | public func off() { 29 | print("🌒 Off") 30 | ledPin.value = 0 31 | relayPin.value = 0 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /source/Sources/Home/i2cdetect.swift: -------------------------------------------------------------------------------- 1 | import SwiftyGPIO 2 | 3 | public func i2c_detect() { 4 | let i2cs = SwiftyGPIO.hardwareI2Cs(for:.RaspberryPi3)! 5 | let i2c = i2cs[1] 6 | 7 | print("Detecting devices on the I2C bus:\n") 8 | outer: for i in 0x0...0x7 { 9 | if i == 0 { 10 | print(" 0 1 2 3 4 5 6 7 8 9 a b c d e f") 11 | } 12 | for j in 0x0...0xf { 13 | if j == 0 { 14 | print(String(format:"%x0",i), terminator: "") 15 | } 16 | // Test within allowed range 0x3...0x77 17 | if (i==0) && (j<3) {print(" ", terminator: "");continue} 18 | if (i>=7) && (j>=7) {break outer} 19 | 20 | print(" \(i2c.isReachable(i<<4 + j) ? " x" : " ." )", terminator: "") 21 | } 22 | print() 23 | } 24 | print("\n") 25 | } 26 | 27 | public func i2c() { 28 | let i2cs = SwiftyGPIO.hardwareI2Cs(for:.RaspberryPi3)! 29 | print("I2C's \(i2cs)") 30 | let i2c = i2cs[1] 31 | i2c.setPEC(0x45, enabled: true) 32 | 33 | // print("Read.") 34 | // print("Read: \(i2c.readByte(0x45))") 35 | // print("Read: \(i2c.readByte(0x45))") 36 | // sleep(0.1) 37 | // print("Read: \(i2c.readByte(0x45))") 38 | 39 | print("Write.") 40 | // i2c.setPEC(0x45, enabled: true) 41 | // let array: [UInt8] = [0x2C, 0x06] 42 | // print("Writing: \(i2c.writeData(0x45, command: 0, values:array))") 43 | // print("Writing: \(i2c.writeWord(0x45, command: 0, value:0x062C))") 44 | // print("Writing: \(i2c.writeWord(0x45, command: 0, value:0x2C06))") 45 | 46 | print("Writing: \(i2c.writeByte(0x45, value:0x2C))") 47 | 48 | 49 | 50 | // sleep(0.1) 51 | // print("Writing: \(i2c.writeByte(0x45 , value:0x06))") 52 | 53 | // Reading register 0 of the device with address 0x68 54 | print("Read: \(i2c.readWord(0x45, command: 0))") 55 | // Reading register 1 of the device with address 0x68 56 | // print("Register 1" + i2c.readByte(0x45, command: 1)) 57 | 58 | } 59 | // i2c_detect() 60 | 61 | // i2c() -------------------------------------------------------------------------------- /source/Sources/RaspberrySwift/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // 4 | 5 | import Foundation 6 | import Home 7 | 8 | func switch_toggle() { 9 | guard let light = LightSwitch() else { print("Failed to create switch"); return } 10 | let reader = AnalogReader() 11 | 12 | print("Temperature: \(reader.readValue())") 13 | for _ in 1...5 { 14 | light.on() 15 | usleep(500_000) 16 | light.off() 17 | sleep(500_000) 18 | } 19 | } 20 | 21 | switch_toggle() 22 | 23 | func main() -> Int { 24 | print("Main") 25 | return 0 26 | } 27 | -------------------------------------------------------------------------------- /tank/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | -------------------------------------------------------------------------------- /tank/Package.pins: -------------------------------------------------------------------------------- 1 | { 2 | "autoPin": true, 3 | "pins": [ 4 | { 5 | "package": "SwiftyGPIO", 6 | "reason": null, 7 | "repositoryURL": "https://github.com/uraimo/SwiftyGPIO.git", 8 | "version": "0.9.13" 9 | } 10 | ], 11 | "version": 1 12 | } -------------------------------------------------------------------------------- /tank/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:3.1 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Tank", 7 | dependencies: [ 8 | .Package(url: "https://github.com/uraimo/SwiftyGPIO.git", majorVersion: 0), 9 | ] 10 | ) 11 | -------------------------------------------------------------------------------- /tank/Sources/RaspberryTank/Motor.swift: -------------------------------------------------------------------------------- 1 | import SwiftyGPIO 2 | 3 | private let i2cs = SwiftyGPIO.hardwareI2Cs(for:.RaspberryPi3)! 4 | private let i2c = i2cs[1] 5 | 6 | // Registers/etc. 7 | let ADDRESS: Int = 0x6f 8 | let ON_L: UInt8 = 0x06 9 | let ON_H: UInt8 = 0x07 10 | let OFF_L: UInt8 = 0x08 11 | let OFF_H: UInt8 = 0x09 12 | 13 | //"Sets a single PWM channel" 14 | func setPWM(_ channel: UInt8, _ on: UInt16, _ off: UInt16) { 15 | // print(" - Set PWM: \(channel) on: \(on) off: \(off)") 16 | i2c.writeByte(ADDRESS, command: ON_L + 4 * channel, value: UInt8(on & 0xFF)) 17 | i2c.writeByte(ADDRESS, command: ON_H + 4 * channel, value: UInt8(on >> 8)) 18 | i2c.writeByte(ADDRESS, command: OFF_L + 4 * channel, value: UInt8(off & 0xFF)) 19 | i2c.writeByte(ADDRESS, command: OFF_H + 4 * channel, value: UInt8(off >> 8)) 20 | } 21 | 22 | public struct Motor { 23 | let pin1: UInt8 24 | let pin2: UInt8 25 | let pwm: UInt8 26 | let name: String 27 | 28 | enum level { 29 | case LOW 30 | case HIGH 31 | } 32 | 33 | public func backward() { 34 | // print(" \(name) ⇒ Backward") 35 | setPin(pin2, .LOW) 36 | setPin(pin1, .HIGH) 37 | } 38 | 39 | public func forward() { 40 | // print(" \(name) ⇒ Forward") 41 | setPin(pin1, .LOW) 42 | setPin(pin2, .HIGH) 43 | } 44 | 45 | public func stop() { 46 | // print(" \(name) ⇒ Stop") 47 | setPin(pin1, .LOW) 48 | setPin(pin2, .LOW) 49 | } 50 | 51 | public func setSpeed(_ speed: UInt16) { 52 | // print(" - Set speed: \(speed)") 53 | setPWM(pwm, 0, speed*16) 54 | } 55 | 56 | func setPin(_ pin: UInt8, _ level: level) { 57 | // print(" - Set pin: \(pin) \(level)") 58 | let value: UInt16 = (level == .HIGH) ? 4096 : 0 59 | setPWM(pin, value, 0) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tank/Sources/RaspberryTank/Tank.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public class Tank { 4 | let right = Motor(pin1: 9, pin2: 10, pwm: 8, name: "Right") 5 | let left = Motor(pin1: 12, pin2: 11, pwm: 13, name: "Left") 6 | 7 | init() { 8 | print("Tank Created:") 9 | print(" Left: \(left)") 10 | print(" Right: \(right)") 11 | } 12 | 13 | public func drive() { 14 | print("Forward ⇧ ⇧") 15 | left.forward() 16 | right.forward() 17 | sleep(1) 18 | stop() 19 | } 20 | 21 | public func turnLeft() { 22 | print("Left ⇩ ⇧") 23 | left.backward() 24 | right.forward() 25 | sleep(2) 26 | stop() 27 | } 28 | 29 | public func turnRight() { 30 | print("Right ⇧ ⇩") 31 | left.forward() 32 | right.backward() 33 | sleep(2) 34 | stop() 35 | } 36 | 37 | public func stop() { 38 | // print("Stop ⌧ ⇎") 39 | left.stop() 40 | right.stop() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tank/Sources/RaspberryTank/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Create our own interface to the tank 4 | let tank = Tank() 5 | 6 | tank.drive() 7 | tank.turnLeft() 8 | tank.turnRight() 9 | tank.drive() 10 | tank.stop() 11 | -------------------------------------------------------------------------------- /tank/Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import raspberryTankTests 3 | 4 | XCTMain([ 5 | testCase(raspberryTankTests.allTests), 6 | ]) 7 | -------------------------------------------------------------------------------- /tank/Tests/raspberryTankTests/raspberryTankTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Tank 3 | 4 | class raspberryTankTests: XCTestCase { 5 | func testMotorsAreCreated() { 6 | XCTAssertNotNil(Tank().left) 7 | XCTAssertNotNil(Tank().left) 8 | } 9 | 10 | 11 | static var allTests = [ 12 | ("testMotorsAreCreated", testMotorsAreCreated), 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tooling/common.rb: -------------------------------------------------------------------------------- 1 | def system_and_log(message) 2 | gray = 37 3 | puts "\e[#{gray}m#{message}\e[0m" 4 | success = system message 5 | if success == false 6 | error "Failed to run command: " + message 7 | abort() 8 | end 9 | end 10 | 11 | def log(message) 12 | blue_color_code = 34 13 | puts "\e[#{blue_color_code}m#{message}\e[0m" 14 | system message 15 | end 16 | 17 | def error(message) 18 | red_color_code = 31 19 | puts "\e[#{red_color_code}m#{message}\e[0m" 20 | system message 21 | end -------------------------------------------------------------------------------- /tooling/swift_build.rb: -------------------------------------------------------------------------------- 1 | 2 | ARGS = '-module-cache-path build -Onone' 3 | SOURCES = 'source/Home/DataStore.swift source/Home/AnalogReader.swift source/Home/LightSwitch.swift' 4 | # SOURCES = 'DataStore.swift' 5 | 6 | def log(message) 7 | blue_color_code = 34 8 | puts "\e[#{blue_color_code}m#{message}\e[0m" 9 | end 10 | 11 | def build_home 12 | log 'Building Home' 13 | sh "swiftc #{SOURCES} #{ARGS} -emit-library -module-name Home -emit-module -o build/libHome.dylib -v -num-threads 4 -emit-dependencies" 14 | # sh "swiftc #{SOURCES} -v" 15 | 16 | end 17 | 18 | def build_main 19 | log 'Building main' 20 | system 'LD_LIBRARY_PATH=/home/steven/workspace/raspberry-swift/build' 21 | system 'echo $LD_LIBRARY_PATH' 22 | sh "swiftc #{ARGS} -I build -L build -lHome source/main.swift -o build/main -v -Xlinker -v" 23 | end 24 | 25 | def build_individual 26 | system_and_log 'swiftc -j4 \ 27 | source/SwiftyGPIO/Mailbox.swift source/SwiftyGPIO/SunXi.swift source/SwiftyGPIO/UART.swift source/SwiftyGPIO/I2C.swift source/SwiftyGPIO/Presets.swift source/SwiftyGPIO/SwiftyGPIO.swift source/main.swift -o .build/main -v' 28 | system_and_log './build/main' 29 | end 30 | 31 | def self.clean 32 | sh 'rm -rf build/*' 33 | end 34 | --------------------------------------------------------------------------------