├── .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 | 
4 |
5 | Swift 3.1 app on the Raspberry Pi 3
6 |
7 | [](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 |
--------------------------------------------------------------------------------