They don't care about us中文歌词

文件名:

They don't care about us.txt

[00:47.43]Situation, Aggravation, Everybody, Allegation
[00:50.06]In the suite, On the news Everybody dog food Bang bang
[00:53.61]Shock dead, Everybody's Gone mad
[00:55.58]All I wanna say is that they don't really care about us
[01:00.87]All I wanna say is that they don't really care about us
[01:06.14]Beat me, Hate me, You can never Break me
[01:08.86]Will me, thrill me, you can never kill me
[01:11.48]Jew me, sue me, everybody do me, kick me
[01:15.39]Don't you Black or white me
[01:16.85]All I wanna say is that they don't really care about us
[01:22.09]All I wanna say is that they don't really care about us
[01:27.58]Tell me what has become of my life
[01:30.25]I have a wife and two children who love me
[01:33.03]I am the victim of police brutality, now
[01:38.23]I'm tired of bein' the victim of hate,
[01:40.94]Your rapin' me of my pride
[01:42.65]Oh for God's sake
[01:44.10]I look to heaven to fulfill its prophecy...
[01:47.06]Set me free
[01:48.68]Skinhead, Deadhead, Everybody, Gone bad
[01:48.68]Skinhead, Deadhead, Everybody, Gone bad
[01:51.35]Situation, Aggravation, Everybody, Allegation
[01:54.00]In the suite, On the news Everybody, Dog food
[01:56.64]Black man, black mail, throw the brother in jail
[01:59.32]All I wanna say is that they don't really care about us
[02:04.58]All I wanna say is that they don't really care about us
[02:10.24]Tell me what has become of my rights
[02:13.01]Am I invisible 'cause you ignore me?
[02:15.61]Your proclamation promised me free liberty, now
[02:20.59]I'm tired of bein' the victim of shame
[02:23.42]They're throwin' me in a class with a bad name
[02:26.23]I can't believe this is the land from witch I came
[02:30.71]You know I really do hate to say it
[02:33.35]The government don't wanna see
[02:36.01]But if roosevelt was livin', he wouldn't let this be, no no
[02:41.80]Skinhead, Deadhead, Everybody, Gone bad
[02:44.45]Situation, speculation, Everybody, litigation
[02:47.04]Beat me, bash me, you can never trash me
[02:49.71]hit me, kick me , you can never get me
[02:52.40]All I wanna say is that they don't really care about us
[02:57.72]All I wanna say is that they don't really care about us
[03:24.58]Some things in life they just don't wanna see
[03:28.83]But if Martin Luther was livin'
[03:31.90]He wouldn't let this be
[03:34.92]Skinhead, Deadhead, Everybody, Gone bad
[03:37.58]Situation, Aggravation, Everybody, Allegation
[03:40.18]In the suite, On the news Everybody, Dog food
[03:42.81]Kick me, kike me, don't you wrong or right me
[03:45.56]All I wanna say is that they don't really care about us
[03:50.83]All I wanna say is that they don't really care about us
[03:56.09]All I wanna say is that they don't really care about us
[04:01.64]All I wanna say is that they don't really care about us
[04:04.13]All I wanna say is that they don't really care about us
[04:06.72]All I wanna say is that they don't really care about us

文件名:

They don't care about us-cn.txt

人面兽心, 行尸走肉, 所有人, 变坏
见风使舵, 投机倒把, 所有人, 起诉
在庭上,新闻里,所有人一文不值
吓死, 所有人愤怒了
我只是想说有谁在乎我们
我只是想说有谁在乎我们
打击我,憎恨我,你永远无法击垮我
利诱我, 威胁我, 你永远无法杀死我
我是犹太人, 你就要告我, 所有人都想整我,踢我
你颠倒是非黑白
我只是想说有谁在乎我们
我只是想说有谁在乎我们
告诉我我的生活变成了什么
我有个爱着我的妻子和两个孩子
我现在是个警察暴力的受害者了
我已厌倦作为厌恶的受害者
你在掠夺我的自豪
噢 究竟为了什么
我这是想把人间变为天堂...
放过我
人面兽心, 行尸走肉, 所有人, 变坏
人面兽心, 行尸走肉, 所有人, 变坏
见风使舵, 投机倒把, 所有人, 起诉
在庭上,新闻里,所有人一文不值
小人,告密,患难同胞,投入监狱
我只是想说有谁在乎我们
我只是想说有谁在乎我们
告诉我什么是我的权力
你对我视而不见我就不存在了吗?
你曾向我承诺自由
我已厌倦成为阴谋的受害者
他们把对我进行肆意的毁谤
我无法相信这就是养育我的那片土地
你知道我真的不想这么说
政府也不想看到这
如果罗斯福活着,他绝不会让这一切发生,不,不
人面兽心, 行尸走肉, 所有人, 变坏
见风使舵, 投机倒把, 所有人, 起诉
打击我,憎恨我,你永远无法击废我
袭击我,践踏我,你永远无法打垮我
我只是想说有谁在乎我们
我只是想说有谁在乎我们
生命中有些事是他们不想看到的
但如果马丁路德金活着的话
他绝不会允许它发生
人面兽心, 行尸走肉, 所有人, 变坏
见风使舵, 投机倒把, 所有人, 起诉
在庭上,新闻里,所有人一文不值
绊倒我,毁谤我,你指手画脚
我只是想说有谁在乎我们
我只是想说有谁在乎我们
我只是想说有谁在乎我们
我只是想说有谁在乎我们
我只是想说有谁在乎我们
我只是想说有谁在乎我们

合并:

import java.io.*; import java.util.*; public class LrcChina { public static void main(String[] args) { try{ //中文歌词 List<String> china = new ArrayList<String>(); BufferedReader cbw = new BufferedReader( new FileReader("They don't care about us-cn.txt")); String s = ""; while(( s= cbw.readLine()) != null){ china.add(s); } //英语歌词 List<String> english = new ArrayList<String>(); BufferedReader ebw = new BufferedReader( new FileReader("They don't care about us.txt")); //结果容器 List<String> result = new ArrayList<String>(); int i = 0; String x = ""; while((x = ebw.readLine()) != null) { String chinalrc =china.get(i); String replace = x.replaceAll("(//[.+//]).+","$1"+chinalrc); result.add(replace); i++; if(i == china.size()) break; } Iterator it = result.iterator(); BufferedWriter chinaLRC = new BufferedWriter( new FileWriter("ChinaLrc.txt")); while(it.hasNext()){ String OY = (String)it.next(); System.out.println(OY); chinaLRC.write(OY); chinaLRC.newLine(); } chinaLRC.flush(); chinaLRC.close(); cbw.close(); ebw.close(); }catch(Exception e){ e.printStackTrace(); } } }

chinaLRC.txt:

[00:47.43]人面兽心, 行尸走肉, 所有人, 变坏
[00:50.06]见风使舵, 投机倒把, 所有人, 起诉
[00:53.61]在庭上,新闻里,所有人一文不值
[00:55.58]吓死, 所有人愤怒了
[01:00.87]我只是想说有谁在乎我们
[01:06.14]我只是想说有谁在乎我们
[01:08.86]打击我,憎恨我,你永远无法击垮我
[01:11.48]利诱我, 威胁我, 你永远无法杀死我
[01:15.39]我是犹太人, 你就要告我, 所有人都想整我,踢我
[01:16.85]你颠倒是非黑白
[01:22.09]我只是想说有谁在乎我们
[01:27.58]我只是想说有谁在乎我们
[01:30.25]告诉我我的生活变成了什么
[01:33.03]我有个爱着我的妻子和两个孩子
[01:38.23]我现在是个警察暴力的受害者了
[01:40.94]我已厌倦作为厌恶的受害者
[01:42.65]你在掠夺我的自豪
[01:44.10]噢 究竟为了什么
[01:47.06]我这是想把人间变为天堂...
[01:48.68]放过我
[01:48.68]人面兽心, 行尸走肉, 所有人, 变坏
[01:51.35]人面兽心, 行尸走肉, 所有人, 变坏
[01:54.00]见风使舵, 投机倒把, 所有人, 起诉
[01:56.64]在庭上,新闻里,所有人一文不值
[01:59.32]小人,告密,患难同胞,投入监狱
[02:04.58]我只是想说有谁在乎我们
[02:10.24]我只是想说有谁在乎我们
[02:13.01]告诉我什么是我的权力
[02:15.61]你对我视而不见我就不存在了吗?
[02:20.59]你曾向我承诺自由
[02:23.42]我已厌倦成为阴谋的受害者
[02:26.23]他们把对我进行肆意的毁谤
[02:30.71]我无法相信这就是养育我的那片土地
[02:33.35]你知道我真的不想这么说
[02:36.01]政府也不想看到这
[02:41.80]如果罗斯福活着,他绝不会让这一切发生,不,不
[02:44.45]人面兽心, 行尸走肉, 所有人, 变坏
[02:47.04]见风使舵, 投机倒把, 所有人, 起诉
[02:49.71]打击我,憎恨我,你永远无法击废我
[02:52.40]袭击我,践踏我,你永远无法打垮我
[02:57.72]我只是想说有谁在乎我们
[03:24.58]我只是想说有谁在乎我们
[03:28.83]生命中有些事是他们不想看到的
[03:31.90]但如果马丁路德金活着的话
[03:34.92]他绝不会允许它发生
[03:37.58]人面兽心, 行尸走肉, 所有人, 变坏
[03:40.18]见风使舵, 投机倒把, 所有人, 起诉
[03:42.81]在庭上,新闻里,所有人一文不值
[03:45.56]绊倒我,毁谤我,你指手画脚
[03:50.83]我只是想说有谁在乎我们
[03:56.09]我只是想说有谁在乎我们
[04:01.64]我只是想说有谁在乎我们
[04:04.13]我只是想说有谁在乎我们
[04:06.72]我只是想说有谁在乎我们

Michael Jackson I Love You.

/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H #define __EXPORTED_HEADERS__ #include <uapi/linux/types.h> #ifndef __ASSEMBLY__ #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] typedef u32 __kernel_dev_t; typedef __kernel_fd_set fd_set; typedef __kernel_dev_t dev_t; typedef __kernel_ulong_t ino_t; typedef __kernel_mode_t mode_t; typedef unsigned short umode_t; typedef u32 nlink_t; typedef __kernel_off_t off_t; typedef __kernel_pid_t pid_t; typedef __kernel_daddr_t daddr_t; typedef __kernel_key_t key_t; typedef __kernel_suseconds_t suseconds_t; typedef __kernel_timer_t timer_t; typedef __kernel_clockid_t clockid_t; typedef __kernel_mqd_t mqd_t; typedef _Bool bool; typedef __kernel_uid32_t uid_t; typedef __kernel_gid32_t gid_t; typedef __kernel_uid16_t uid16_t; typedef __kernel_gid16_t gid16_t; typedef unsigned long uintptr_t; #ifdef CONFIG_HAVE_UID16 /* This is defined by include/asm-{arch}/posix_types.h */ typedef __kernel_old_uid_t old_uid_t; typedef __kernel_old_gid_t old_gid_t; #endif /* CONFIG_UID16 */ #if defined(__GNUC__) typedef __kernel_loff_t loff_t; #endif /* * The following typedefs are also protected by individual ifdefs for * historical reasons: */ #ifndef _SIZE_T #define _SIZE_T typedef __kernel_size_t size_t; #endif #ifndef _SSIZE_T #define _SSIZE_T typedef __kernel_ssize_t ssize_t; #endif #ifndef _PTRDIFF_T #define _PTRDIFF_T typedef __kernel_ptrdiff_t ptrdiff_t; #endif #ifndef _CLOCK_T #define _CLOCK_T typedef __kernel_clock_t clock_t; #endif #ifndef _CADDR_T #define _CADDR_T typedef __kernel_caddr_t caddr_t; #endif /* bsd */ typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; /* sysv */ typedef unsigned char unchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; #ifndef __BIT_TYPES_DEFINED__ #define __BIT_TYPES_DEFINED__ typedef u8 u_int8_t; typedef s8 int8_t; typedef u16 u_int16_t; typedef s16 int16_t; typedef u32 u_int32_t; typedef s32 int32_t; #endif /* !(__BIT_TYPES_DEFINED__) */ typedef u8 uint8_t; typedef u16 uint16_t; typedef u32 uint32_t; #if defined(__GNUC__) typedef u64 uint64_t; typedef u64 u_int64_t; typedef s64 int64_t; #endif /* this is a special 64bit data type that is 8-byte aligned */ #define aligned_u64 __aligned_u64 #define aligned_be64 __aligned_be64 #define aligned_le64 __aligned_le64 /** * The type used for indexing onto a disc or disc partition. * * Linux always considers sectors to be 512 bytes long independently * of the devices real block size. * * blkcnt_t is the type of the inode's block count. */ typedef u64 sector_t; typedef u64 blkcnt_t; /* * The type of an index into the pagecache. */ #define pgoff_t unsigned long /* * A dma_addr_t can hold any valid DMA address, i.e., any address returned * by the DMA API. * * If the DMA API only uses 32-bit addresses, dma_addr_t need only be 32 * bits wide. Bus addresses, e.g., PCI BARs, may be wider than 32 bits, * but drivers do memory-mapped I/O to ioremapped kernel virtual addresses, * so they don't care about the size of the actual bus addresses. */ #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT typedef u64 dma_addr_t; #else typedef u32 dma_addr_t; #endif typedef unsigned int __bitwise gfp_t; typedef unsigned int __bitwise slab_flags_t; typedef unsigned int __bitwise fmode_t; #ifdef CONFIG_PHYS_ADDR_T_64BIT typedef u64 phys_addr_t; #else typedef u32 phys_addr_t; #endif typedef phys_addr_t resource_size_t; /* * This type is the placeholder for a hardware interrupt number. It has to be * big enough to enclose whatever representation is used by a given platform. */ typedef unsigned long irq_hw_number_t; typedef struct { int counter; } atomic_t; #define ATOMIC_INIT(i) { (i) } #ifdef CONFIG_64BIT typedef struct { s64 counter; } atomic64_t; #endif struct list_head { struct list_head *next, *prev; }; struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; }; struct ustat { __kernel_daddr_t f_tfree; #ifdef CONFIG_ARCH_32BIT_USTAT_F_TINODE unsigned int f_tinode; #else unsigned long f_tinode; #endif char f_fname[6]; char f_fpack[6]; }; /** * struct callback_head - callback structure for use with RCU and task_work * @next: next update requests in a list * @func: actual update function to call after the grace period. * * The struct is aligned to size of pointer. On most architectures it happens * naturally due ABI requirements, but some architectures (like CRIS) have * weird ABI and we need to ask it explicitly. * * The alignment is required to guarantee that bit 0 of @next will be * clear under normal conditions -- as long as we use call_rcu() or * call_srcu() to queue the callback. * * This guarantee is important for few reasons: * - future call_rcu_lazy() will make use of lower bits in the pointer; * - the structure shares storage space in struct page with @compound_head, * which encode PageTail() in bit 0. The guarantee is needed to avoid * false-positive PageTail(). */ struct callback_head { struct callback_head *next; void (*func)(struct callback_head *head); } __attribute__((aligned(sizeof(void *)))); #define rcu_head callback_head typedef void (*rcu_callback_t)(struct rcu_head *head); typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func); typedef void (*swap_func_t)(void *a, void *b, int size); typedef int (*cmp_r_func_t)(const void *a, const void *b, const void *priv); typedef int (*cmp_func_t)(const void *a, const void *b); #endif /* __ASSEMBLY__ */ #endif /* _LINUX_TYPES_H */
08-09
/* This is a library written for the BNO080 SparkFun sells these at its website: www.sparkfun.com Do you like this library? Help support SparkFun. Buy a board! https://www.sparkfun.com/products/14586 Written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 The BNO080 IMU is a powerful triple axis gyro/accel/magnetometer coupled with an ARM processor to maintain and complete all the complex calculations for various VR, inertial, step counting, and movement operations. This library handles the initialization of the BNO080 and is able to query the sensor for different readings. https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library Development environment specifics: Arduino IDE 1.8.3 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "SparkFun_BNO080_Arduino_Library.h" //Attempt communication with the device //Return true if we got a 'Polo' back from Marco boolean BNO080::begin(uint8_t deviceAddress, TwoWire &wirePort) { _deviceAddress = deviceAddress; //If provided, store the I2C address from user _i2cPort = &wirePort; //Grab which port the user wants us to use //We expect caller to begin their I2C port, with the speed of their choice external to the library //But if they forget, we start the hardware here. _i2cPort->begin(); //Begin by resetting the IMU softReset(); //Check communication with device shtpData[0] = SHTP_REPORT_PRODUCT_ID_REQUEST; //Request the product ID and reset info shtpData[1] = 0; //Reserved //Transmit packet on channel 2, 2 bytes sendPacket(CHANNEL_CONTROL, 2); //Now we wait for response if (receivePacket() == true) { if (shtpData[0] == SHTP_REPORT_PRODUCT_ID_RESPONSE) { return(true); } } return(false); //Something went wrong } //Calling this function with nothing sets the debug port to Serial //You can also call it with other streams like Serial1, SerialUSB, etc. void BNO080::enableDebugging(Stream &debugPort) { _debugPort = &debugPort; _printDebug = true; } //Updates the latest variables if possible //Returns false if new readings are not available bool BNO080::dataAvailable(void) { if (receivePacket() == true) { //Check to see if this packet is a sensor reporting its data to us if (shtpHeader[2] == CHANNEL_REPORTS && shtpData[0] == SHTP_REPORT_BASE_TIMESTAMP) { parseInputReport(); //This will update the rawAccelX, etc variables depending on which feature report is found return(true); } } return(false); } //This function pulls the data from the input report //The input reports vary in length so this function stores the various 16-bit values as globals //Unit responds with packet that contains the following: //shtpHeader[0:3]: First, a 4 byte header //shtpData[0:4]: Then a 5 byte timestamp of microsecond clicks since reading was taken //shtpData[5 + 0]: Then a feature report ID (0x01 for Accel, 0x05 for Rotation Vector) //shtpData[5 + 1]: Sequence number (See 6.5.18.2) //shtpData[5 + 2]: Status //shtpData[3]: Delay //shtpData[4:5]: i/accel x/gyro x/etc //shtpData[6:7]: j/accel y/gyro y/etc //shtpData[8:9]: k/accel z/gyro z/etc //shtpData[10:11]: real/gyro temp/etc //shtpData[12:13]: Accuracy estimate void BNO080::parseInputReport(void) { //Calculate the number of data bytes in this packet int16_t dataLength = ((uint16_t)shtpHeader[1] << 8 | shtpHeader[0]); dataLength &= ~(1 << 15); //Clear the MSbit. This bit indicates if this package is a continuation of the last. //Ignore it for now. TODO catch this as an error and exit dataLength -= 4; //Remove the header bytes from the data count uint8_t status = shtpData[5 + 2] & 0x03; //Get status bits uint16_t data1 = (uint16_t)shtpData[5 + 5] << 8 | shtpData[5 + 4]; uint16_t data2 = (uint16_t)shtpData[5 + 7] << 8 | shtpData[5 + 6]; uint16_t data3 = (uint16_t)shtpData[5 + 9] << 8 | shtpData[5 + 8]; uint16_t data4 = 0; uint16_t data5 = 0; if(dataLength - 5 > 9) { data4= (uint16_t)shtpData[5 + 11] << 8 | shtpData[5 + 10]; } if(dataLength - 5 > 11) { data5 = (uint16_t)shtpData[5 + 13] << 8 | shtpData[5 + 12]; } //Store these generic values to their proper global variable if(shtpData[5] == SENSOR_REPORTID_ACCELEROMETER) { accelAccuracy = status; rawAccelX = data1; rawAccelY = data2; rawAccelZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_LINEAR_ACCELERATION) { accelLinAccuracy = status; rawLinAccelX = data1; rawLinAccelY = data2; rawLinAccelZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_GYROSCOPE) { gyroAccuracy = status; rawGyroX = data1; rawGyroY = data2; rawGyroZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_MAGNETIC_FIELD) { magAccuracy = status; rawMagX = data1; rawMagY = data2; rawMagZ = data3; } else if(shtpData[5] == SENSOR_REPORTID_ROTATION_VECTOR || shtpData[5] == SENSOR_REPORTID_GAME_ROTATION_VECTOR) { quatAccuracy = status; rawQuatI = data1; rawQuatJ = data2; rawQuatK = data3; rawQuatReal = data4; rawQuatRadianAccuracy = data5; //Only available on rotation vector, not game rot vector } else if(shtpData[5] == SENSOR_REPORTID_STEP_COUNTER) { stepCount = data3; //Bytes 8/9 } else if(shtpData[5] == SENSOR_REPORTID_STABILITY_CLASSIFIER) { stabilityClassifier = shtpData[5 + 4]; //Byte 4 only } else if(shtpData[5] == SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER) { activityClassifier = shtpData[5 + 5]; //Most likely state //Load activity classification confidences into the array for(uint8_t x = 0 ; x < 9 ; x++) //Hardcoded to max of 9. TODO - bring in array size _activityConfidences[x] = shtpData[5 + 6 + x]; //5 bytes of timestamp, byte 6 is first confidence byte } else { //This sensor report ID is unhandled. //See reference manual to add additional feature reports as needed } //TODO additional feature reports may be strung together. Parse them all. } //Return the rotation vector quaternion I float BNO080::getQuatI() { float quat = qToFloat(rawQuatI, rotationVector_Q1); return(quat); } //Return the rotation vector quaternion J float BNO080::getQuatJ() { float quat = qToFloat(rawQuatJ, rotationVector_Q1); return(quat); } //Return the rotation vector quaternion K float BNO080::getQuatK() { float quat = qToFloat(rawQuatK, rotationVector_Q1); return(quat); } //Return the rotation vector quaternion Real float BNO080::getQuatReal() { float quat = qToFloat(rawQuatReal, rotationVector_Q1); return(quat); } //Return the rotation vector accuracy float BNO080::getQuatRadianAccuracy() { float quat = qToFloat(rawQuatRadianAccuracy, rotationVector_Q1); return(quat); } //Return the acceleration component uint8_t BNO080::getQuatAccuracy() { return(quatAccuracy); } //Return the acceleration component float BNO080::getAccelX() { float accel = qToFloat(rawAccelX, accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getAccelY() { float accel = qToFloat(rawAccelY, accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getAccelZ() { float accel = qToFloat(rawAccelZ, accelerometer_Q1); return(accel); } //Return the acceleration component uint8_t BNO080::getAccelAccuracy() { return(accelAccuracy); } // linear acceleration, i.e. minus gravity //Return the acceleration component float BNO080::getLinAccelX() { float accel = qToFloat(rawLinAccelX, linear_accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getLinAccelY() { float accel = qToFloat(rawLinAccelY, linear_accelerometer_Q1); return(accel); } //Return the acceleration component float BNO080::getLinAccelZ() { float accel = qToFloat(rawLinAccelZ, linear_accelerometer_Q1); return(accel); } //Return the acceleration component uint8_t BNO080::getLinAccelAccuracy() { return(accelLinAccuracy); } //Return the gyro component float BNO080::getGyroX() { float gyro = qToFloat(rawGyroX, gyro_Q1); return(gyro); } //Return the gyro component float BNO080::getGyroY() { float gyro = qToFloat(rawGyroY, gyro_Q1); return(gyro); } //Return the gyro component float BNO080::getGyroZ() { float gyro = qToFloat(rawGyroZ, gyro_Q1); return(gyro); } //Return the gyro component uint8_t BNO080::getGyroAccuracy() { return(gyroAccuracy); } //Return the magnetometer component float BNO080::getMagX() { float mag = qToFloat(rawMagX, magnetometer_Q1); return(mag); } //Return the magnetometer component float BNO080::getMagY() { float mag = qToFloat(rawMagY, magnetometer_Q1); return(mag); } //Return the magnetometer component float BNO080::getMagZ() { float mag = qToFloat(rawMagZ, magnetometer_Q1); return(mag); } //Return the mag component uint8_t BNO080::getMagAccuracy() { return(magAccuracy); } //Return the step count uint16_t BNO080::getStepCount() { return(stepCount); } //Return the stability classifier uint8_t BNO080::getStabilityClassifier() { return(stabilityClassifier); } //Return the activity classifier uint8_t BNO080::getActivityClassifier() { return(activityClassifier); } //Given a record ID, read the Q1 value from the metaData record in the FRS (ya, it's complicated) //Q1 is used for all sensor data calculations int16_t BNO080::getQ1(uint16_t recordID) { //Q1 is always the lower 16 bits of word 7 uint16_t q = readFRSword(recordID, 7) & 0xFFFF; //Get word 7, lower 16 bits return(q); } //Given a record ID, read the Q2 value from the metaData record in the FRS //Q2 is used in sensor bias int16_t BNO080::getQ2(uint16_t recordID) { //Q2 is always the upper 16 bits of word 7 uint16_t q = readFRSword(recordID, 7) >> 16; //Get word 7, upper 16 bits return(q); } //Given a record ID, read the Q3 value from the metaData record in the FRS //Q3 is used in sensor change sensitivity int16_t BNO080::getQ3(uint16_t recordID) { //Q3 is always the upper 16 bits of word 8 uint16_t q = readFRSword(recordID, 8) >> 16; //Get word 8, upper 16 bits return(q); } //Given a record ID, read the resolution value from the metaData record in the FRS for a given sensor float BNO080::getResolution(uint16_t recordID) { //The resolution Q value are 'the same as those used in the sensor's input report' //This should be Q1. int16_t Q = getQ1(recordID); //Resolution is always word 2 uint32_t value = readFRSword(recordID, 2); //Get word 2 float resolution = qToFloat(value, Q); return(resolution); } //Given a record ID, read the range value from the metaData record in the FRS for a given sensor float BNO080::getRange(uint16_t recordID) { //The resolution Q value are 'the same as those used in the sensor's input report' //This should be Q1. int16_t Q = getQ1(recordID); //Range is always word 1 uint32_t value = readFRSword(recordID, 1); //Get word 1 float range = qToFloat(value, Q); return(range); } //Given a record ID and a word number, look up the word data //Helpful for pulling out a Q value, range, etc. //Use readFRSdata for pulling out multi-word objects for a sensor (Vendor data for example) uint32_t BNO080::readFRSword(uint16_t recordID, uint8_t wordNumber) { if(readFRSdata(recordID, wordNumber, 1) == true) //Get word number, just one word in length from FRS return(metaData[0]); //Return this one word return(0); //Error } //Ask the sensor for data from the Flash Record System //See 6.3.6 page 40, FRS Read Request void BNO080::frsReadRequest(uint16_t recordID, uint16_t readOffset, uint16_t blockSize) { shtpData[0] = SHTP_REPORT_FRS_READ_REQUEST; //FRS Read Request shtpData[1] = 0; //Reserved shtpData[2] = (readOffset >> 0) & 0xFF; //Read Offset LSB shtpData[3] = (readOffset >> 8) & 0xFF; //Read Offset MSB shtpData[4] = (recordID >> 0) & 0xFF; //FRS Type LSB shtpData[5] = (recordID >> 8) & 0xFF; //FRS Type MSB shtpData[6] = (blockSize >> 0) & 0xFF; //Block size LSB shtpData[7] = (blockSize >> 8) & 0xFF; //Block size MSB //Transmit packet on channel 2, 8 bytes sendPacket(CHANNEL_CONTROL, 8); } //Given a sensor or record ID, and a given start/stop bytes, read the data from the Flash Record System (FRS) for this sensor //Returns true if metaData array is loaded successfully //Returns false if failure bool BNO080::readFRSdata(uint16_t recordID, uint8_t startLocation, uint8_t wordsToRead) { uint8_t spot = 0; //First we send a Flash Record System (FRS) request frsReadRequest(recordID, startLocation, wordsToRead); //From startLocation of record, read a # of words //Read bytes until FRS reports that the read is complete while (1) { //Now we wait for response while (1) { uint8_t counter = 0; while(receivePacket() == false) { if(counter++ > 100) return(false); //Give up delay(1); } //We have the packet, inspect it for the right contents //See page 40. Report ID should be 0xF3 and the FRS types should match the thing we requested if (shtpData[0] == SHTP_REPORT_FRS_READ_RESPONSE) if ( ( (uint16_t)shtpData[13] << 8 | shtpData[12]) == recordID) break; //This packet is one we are looking for } uint8_t dataLength = shtpData[1] >> 4; uint8_t frsStatus = shtpData[1] & 0x0F; uint32_t data0 = (uint32_t)shtpData[7] << 24 | (uint32_t)shtpData[6] << 16 | (uint32_t)shtpData[5] << 8 | (uint32_t)shtpData[4]; uint32_t data1 = (uint32_t)shtpData[11] << 24 | (uint32_t)shtpData[10] << 16 | (uint32_t)shtpData[9] << 8 | (uint32_t)shtpData[8]; //Record these words to the metaData array if (dataLength > 0) { metaData[spot++] = data0; } if (dataLength > 1) { metaData[spot++] = data1; } if (spot >= MAX_METADATA_SIZE) { if(_printDebug == true) _debugPort->println(F("metaData array over run. Returning.")); return(true); //We have run out of space in our array. Bail. } if (frsStatus == 3 || frsStatus == 6 || frsStatus == 7) { return(true); //FRS status is read completed! We're done! } } } //Send command to reset IC //Read all advertisement packets from sensor //The sensor has been seen to reset twice if we attempt too much too quickly. //This seems to work reliably. void BNO080::softReset(void) { shtpData[0] = 1; //Reset //Attempt to start communication with sensor sendPacket(CHANNEL_EXECUTABLE, 1); //Transmit packet on channel 1, 1 byte //Read all incoming data and flush it delay(50); while (receivePacket() == true) ; delay(50); while (receivePacket() == true) ; } //Get the reason for the last reset //1 = POR, 2 = Internal reset, 3 = Watchdog, 4 = External reset, 5 = Other uint8_t BNO080::resetReason() { shtpData[0] = SHTP_REPORT_PRODUCT_ID_REQUEST; //Request the product ID and reset info shtpData[1] = 0; //Reserved //Transmit packet on channel 2, 2 bytes sendPacket(CHANNEL_CONTROL, 2); //Now we wait for response if (receivePacket() == true) { if (shtpData[0] == SHTP_REPORT_PRODUCT_ID_RESPONSE) { return(shtpData[1]); } } return(0); } //Given a register value and a Q point, convert to float //See https://en.wikipedia.org/wiki/Q_(number_format) float BNO080::qToFloat(int16_t fixedPointValue, uint8_t qPoint) { float qFloat = fixedPointValue; qFloat *= pow(2, qPoint * -1); return (qFloat); } //Sends the packet to enable the rotation vector void BNO080::enableRotationVector(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_ROTATION_VECTOR, timeBetweenReports); } //Sends the packet to enable the rotation vector void BNO080::enableGameRotationVector(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_GAME_ROTATION_VECTOR, timeBetweenReports); } //Sends the packet to enable the accelerometer void BNO080::enableAccelerometer(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_ACCELEROMETER, timeBetweenReports); } //Sends the packet to enable the accelerometer void BNO080::enableLinearAccelerometer(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_LINEAR_ACCELERATION, timeBetweenReports); } //Sends the packet to enable the gyro void BNO080::enableGyro(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_GYROSCOPE, timeBetweenReports); } //Sends the packet to enable the magnetometer void BNO080::enableMagnetometer(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_MAGNETIC_FIELD, timeBetweenReports); } //Sends the packet to enable the step counter void BNO080::enableStepCounter(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_STEP_COUNTER, timeBetweenReports); } //Sends the packet to enable the Stability Classifier void BNO080::enableStabilityClassifier(uint16_t timeBetweenReports) { setFeatureCommand(SENSOR_REPORTID_STABILITY_CLASSIFIER, timeBetweenReports); } //Sends the packet to enable the various activity classifiers void BNO080::enableActivityClassifier(uint16_t timeBetweenReports, uint32_t activitiesToEnable, uint8_t (&activityConfidences)[9]) { _activityConfidences = activityConfidences; //Store pointer to array setFeatureCommand(SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER, timeBetweenReports, activitiesToEnable); } //Sends the commands to begin calibration of the accelerometer void BNO080::calibrateAccelerometer() { sendCalibrateCommand(CALIBRATE_ACCEL); } //Sends the commands to begin calibration of the gyro void BNO080::calibrateGyro() { sendCalibrateCommand(CALIBRATE_GYRO); } //Sends the commands to begin calibration of the magnetometer void BNO080::calibrateMagnetometer() { sendCalibrateCommand(CALIBRATE_MAG); } //Sends the commands to begin calibration of the planar accelerometer void BNO080::calibratePlanarAccelerometer() { sendCalibrateCommand(CALIBRATE_PLANAR_ACCEL); } //See 2.2 of the Calibration Procedure document 1000-4044 void BNO080::calibrateAll() { sendCalibrateCommand(CALIBRATE_ACCEL_GYRO_MAG); } void BNO080::endCalibration() { sendCalibrateCommand(CALIBRATE_STOP); //Disables all calibrations } //Given a sensor's report ID, this tells the BNO080 to begin reporting the values void BNO080::setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports) { setFeatureCommand(reportID, timeBetweenReports, 0); //No specific config } //Given a sensor's report ID, this tells the BNO080 to begin reporting the values //Also sets the specific config word. Useful for personal activity classifier void BNO080::setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig) { long microsBetweenReports = (long)timeBetweenReports * 1000L; shtpData[0] = SHTP_REPORT_SET_FEATURE_COMMAND; //Set feature command. Reference page 55 shtpData[1] = reportID; //Feature Report ID. 0x01 = Accelerometer, 0x05 = Rotation vector shtpData[2] = 0; //Feature flags shtpData[3] = 0; //Change sensitivity (LSB) shtpData[4] = 0; //Change sensitivity (MSB) shtpData[5] = (microsBetweenReports >> 0) & 0xFF; //Report interval (LSB) in microseconds. 0x7A120 = 500ms shtpData[6] = (microsBetweenReports >> 8) & 0xFF; //Report interval shtpData[7] = (microsBetweenReports >> 16) & 0xFF; //Report interval shtpData[8] = (microsBetweenReports >> 24) & 0xFF; //Report interval (MSB) shtpData[9] = 0; //Batch Interval (LSB) shtpData[10] = 0; //Batch Interval shtpData[11] = 0; //Batch Interval shtpData[12] = 0; //Batch Interval (MSB) shtpData[13] = (specificConfig >> 0) & 0xFF; //Sensor-specific config (LSB) shtpData[14] = (specificConfig >> 8) & 0xFF; //Sensor-specific config shtpData[15] = (specificConfig >> 16) & 0xFF; //Sensor-specific config shtpData[16] = (specificConfig >> 24) & 0xFF; //Sensor-specific config (MSB) //Transmit packet on channel 2, 17 bytes sendPacket(CHANNEL_CONTROL, 17); } //Tell the sensor to do a command //See 6.3.8 page 41, Command request //The caller is expected to set P0 through P8 prior to calling void BNO080::sendCommand(uint8_t command) { shtpData[0] = SHTP_REPORT_COMMAND_REQUEST; //Command Request shtpData[1] = commandSequenceNumber++; //Increments automatically each function call shtpData[2] = command; //Command //Caller must set these /*shtpData[3] = 0; //P0 shtpData[4] = 0; //P1 shtpData[5] = 0; //P2 shtpData[6] = 0; shtpData[7] = 0; shtpData[8] = 0; shtpData[9] = 0; shtpData[10] = 0; shtpData[11] = 0;*/ //Transmit packet on channel 2, 12 bytes sendPacket(CHANNEL_CONTROL, 12); } //This tells the BNO080 to begin calibrating //See page 50 of reference manual and the 1000-4044 calibration doc void BNO080::sendCalibrateCommand(uint8_t thingToCalibrate) { /*shtpData[3] = 0; //P0 - Accel Cal Enable shtpData[4] = 0; //P1 - Gyro Cal Enable shtpData[5] = 0; //P2 - Mag Cal Enable shtpData[6] = 0; //P3 - Subcommand 0x00 shtpData[7] = 0; //P4 - Planar Accel Cal Enable shtpData[8] = 0; //P5 - Reserved shtpData[9] = 0; //P6 - Reserved shtpData[10] = 0; //P7 - Reserved shtpData[11] = 0; //P8 - Reserved*/ for(uint8_t x = 3 ; x < 12 ; x++) //Clear this section of the shtpData array shtpData[x] = 0; if(thingToCalibrate == CALIBRATE_ACCEL) shtpData[3] = 1; else if(thingToCalibrate == CALIBRATE_GYRO) shtpData[4] = 1; else if(thingToCalibrate == CALIBRATE_MAG) shtpData[5] = 1; else if(thingToCalibrate == CALIBRATE_PLANAR_ACCEL) shtpData[7] = 1; else if(thingToCalibrate == CALIBRATE_ACCEL_GYRO_MAG) { shtpData[3] = 1; shtpData[4] = 1; shtpData[5] = 1; } else if(thingToCalibrate == CALIBRATE_STOP) ; //Do nothing, bytes are set to zero //Using this shtpData packet, send a command sendCommand(COMMAND_ME_CALIBRATE); } //This tells the BNO080 to save the Dynamic Calibration Data (DCD) to flash //See page 49 of reference manual and the 1000-4044 calibration doc void BNO080::saveCalibration() { /*shtpData[3] = 0; //P0 - Reserved shtpData[4] = 0; //P1 - Reserved shtpData[5] = 0; //P2 - Reserved shtpData[6] = 0; //P3 - Reserved shtpData[7] = 0; //P4 - Reserved shtpData[8] = 0; //P5 - Reserved shtpData[9] = 0; //P6 - Reserved shtpData[10] = 0; //P7 - Reserved shtpData[11] = 0; //P8 - Reserved*/ for(uint8_t x = 3 ; x < 12 ; x++) //Clear this section of the shtpData array shtpData[x] = 0; //Using this shtpData packet, send a command sendCommand(COMMAND_DCD); //Save DCD command } //Wait a certain time for incoming I2C bytes before giving up //Returns false if failed boolean BNO080::waitForI2C() { for (uint8_t counter = 0 ; counter < 100 ; counter++) //Don't got more than 255 { if (_i2cPort->available() > 0) return (true); delay(1); } if(_printDebug == true) _debugPort->println(F("I2C timeout")); return (false); } //Check to see if there is any new data available //Read the contents of the incoming packet into the shtpData array boolean BNO080::receivePacket(void) { _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)4); //Ask for four bytes to find out how much data we need to read if (waitForI2C() == false) return (false); //Error //Get the first four bytes, aka the packet header uint8_t packetLSB = _i2cPort->read(); uint8_t packetMSB = _i2cPort->read(); uint8_t channelNumber = _i2cPort->read(); uint8_t sequenceNumber = _i2cPort->read(); //Not sure if we need to store this or not //Store the header info. shtpHeader[0] = packetLSB; shtpHeader[1] = packetMSB; shtpHeader[2] = channelNumber; shtpHeader[3] = sequenceNumber; //Calculate the number of data bytes in this packet int16_t dataLength = ((uint16_t)packetMSB << 8 | packetLSB); dataLength &= ~(1 << 15); //Clear the MSbit. //This bit indicates if this package is a continuation of the last. Ignore it for now. //TODO catch this as an error and exit if (dataLength == 0) { //Packet is empty return (false); //All done } dataLength -= 4; //Remove the header bytes from the data count getData(dataLength); return (true); //We're done! } //Sends multiple requests to sensor until all data bytes are received from sensor //The shtpData buffer has max capacity of MAX_PACKET_SIZE. Any bytes over this amount will be lost. //Arduino I2C read limit is 32 bytes. Header is 4 bytes, so max data we can read per interation is 28 bytes boolean BNO080::getData(uint16_t bytesRemaining) { uint16_t dataSpot = 0; //Start at the beginning of shtpData array //Setup a series of chunked 32 byte reads while (bytesRemaining > 0) { uint16_t numberOfBytesToRead = bytesRemaining; if (numberOfBytesToRead > (I2C_BUFFER_LENGTH-4)) numberOfBytesToRead = (I2C_BUFFER_LENGTH-4); _i2cPort->requestFrom((uint8_t)_deviceAddress, (uint8_t)(numberOfBytesToRead + 4)); if (waitForI2C() == false) return (0); //Error //The first four bytes are header bytes and are throw away _i2cPort->read(); _i2cPort->read(); _i2cPort->read(); _i2cPort->read(); for (uint8_t x = 0 ; x < numberOfBytesToRead ; x++) { uint8_t incoming = _i2cPort->read(); if (dataSpot < MAX_PACKET_SIZE) { shtpData[dataSpot++] = incoming; //Store data into the shtpData array } else { //Do nothing with the data } } bytesRemaining -= numberOfBytesToRead; } return (true); //Done! } //Given the data packet, send the header then the data //Returns false if sensor does not ACK //TODO - Arduino has a max 32 byte send. Break sending into multi packets if needed. boolean BNO080::sendPacket(uint8_t channelNumber, uint8_t dataLength) { uint8_t packetLength = dataLength + 4; //Add four bytes for the header //if(packetLength > I2C_BUFFER_LENGTH) return(false); //You are trying to send too much. Break into smaller packets. _i2cPort->beginTransmission(_deviceAddress); //Send the 4 byte packet header _i2cPort->write(packetLength & 0xFF); //Packet length LSB _i2cPort->write(packetLength >> 8); //Packet length MSB _i2cPort->write(channelNumber); //Channel number _i2cPort->write(sequenceNumber[channelNumber]++); //Send the sequence number, increments with each packet sent, different counter for each channel //Send the user's data packet for (uint8_t i = 0 ; i < dataLength ; i++) { _i2cPort->write(shtpData[i]); } if (_i2cPort->endTransmission() != 0) { return (false); } return (true); } //Pretty prints the contents of the current shtp header and data packets void BNO080::printPacket(void) { if(_printDebug == true) { uint16_t packetLength = (uint16_t)shtpHeader[1] << 8 | shtpHeader[0]; //Print the four byte header _debugPort->print(F("Header:")); for(uint8_t x = 0 ; x < 4 ; x++) { _debugPort->print(F(" ")); if(shtpHeader[x] < 0x10) _debugPort->print(F("0")); _debugPort->print(shtpHeader[x], HEX); } uint8_t printLength = packetLength - 4; if(printLength > 40) printLength = 40; //Artificial limit. We don't want the phone book. _debugPort->print(F(" Body:")); for(uint8_t x = 0 ; x < printLength ; x++) { _debugPort->print(F(" ")); if(shtpData[x] < 0x10) _debugPort->print(F("0")); _debugPort->print(shtpData[x], HEX); } if (packetLength & 1 << 15) { _debugPort->println(F(" [Continued packet] ")); packetLength &= ~(1 << 15); } _debugPort->print(F(" Length:")); _debugPort->print (packetLength); _debugPort->print(F(" Channel:")); if (shtpHeader[2] == 0) _debugPort->print(F("Command")); else if (shtpHeader[2] == 1) _debugPort->print(F("Executable")); else if (shtpHeader[2] == 2) _debugPort->print(F("Control")); else if (shtpHeader[2] == 3) _debugPort->print(F("Sensor-report")); else if (shtpHeader[2] == 4) _debugPort->print(F("Wake-report")); else if (shtpHeader[2] == 5) _debugPort->print(F("Gyro-vector")); else _debugPort->print(shtpHeader[2]); _debugPort->println(); } } /* This is a library written for the BNO080 SparkFun sells these at its website: www.sparkfun.com Do you like this library? Help support SparkFun. Buy a board! https://www.sparkfun.com/products/14586 Written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 The BNO080 IMU is a powerful triple axis gyro/accel/magnetometer coupled with an ARM processor to maintain and complete all the complex calculations for various VR, inertial, step counting, and movement operations. This library handles the initialization of the BNO080 and is able to query the sensor for different readings. https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library Development environment specifics: Arduino IDE 1.8.3 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #if (ARDUINO >= 100) #include "Arduino.h" #else #include "WProgram.h" #endif #include <Wire.h> //The default I2C address for the BNO080 on the SparkX breakout is 0x4B. 0x4A is also possible. #define BNO080_DEFAULT_ADDRESS 0x4B //Platform specific configurations //Define the size of the I2C buffer based on the platform the user has //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) //I2C_BUFFER_LENGTH is defined in Wire.H #define I2C_BUFFER_LENGTH BUFFER_LENGTH #elif defined(__SAMD21G18A__) //SAMD21 uses RingBuffer.h #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE #elif __MK20DX256__ //Teensy #elif ARDUINO_ARCH_ESP32 //ESP32 based platforms #else //The catch-all default is 32 #define I2C_BUFFER_LENGTH 32 #endif //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //Registers const byte CHANNEL_COMMAND = 0; const byte CHANNEL_EXECUTABLE = 1; const byte CHANNEL_CONTROL = 2; const byte CHANNEL_REPORTS = 3; const byte CHANNEL_WAKE_REPORTS = 4; const byte CHANNEL_GYRO = 5; //All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual //These are used for low level communication with the sensor, on channel 2 #define SHTP_REPORT_COMMAND_RESPONSE 0xF1 #define SHTP_REPORT_COMMAND_REQUEST 0xF2 #define SHTP_REPORT_FRS_READ_RESPONSE 0xF3 #define SHTP_REPORT_FRS_READ_REQUEST 0xF4 #define SHTP_REPORT_PRODUCT_ID_RESPONSE 0xF8 #define SHTP_REPORT_PRODUCT_ID_REQUEST 0xF9 #define SHTP_REPORT_BASE_TIMESTAMP 0xFB #define SHTP_REPORT_SET_FEATURE_COMMAND 0xFD //All the different sensors and features we can get reports from //These are used when enabling a given sensor #define SENSOR_REPORTID_ACCELEROMETER 0x01 #define SENSOR_REPORTID_GYROSCOPE 0x02 #define SENSOR_REPORTID_MAGNETIC_FIELD 0x03 #define SENSOR_REPORTID_LINEAR_ACCELERATION 0x04 #define SENSOR_REPORTID_ROTATION_VECTOR 0x05 #define SENSOR_REPORTID_GRAVITY 0x06 #define SENSOR_REPORTID_GAME_ROTATION_VECTOR 0x08 #define SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR 0x09 #define SENSOR_REPORTID_TAP_DETECTOR 0x10 #define SENSOR_REPORTID_STEP_COUNTER 0x11 #define SENSOR_REPORTID_STABILITY_CLASSIFIER 0x13 #define SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER 0x1E //Record IDs from figure 29, page 29 reference manual //These are used to read the metadata for each sensor type #define FRS_RECORDID_ACCELEROMETER 0xE302 #define FRS_RECORDID_GYROSCOPE_CALIBRATED 0xE306 #define FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED 0xE309 #define FRS_RECORDID_ROTATION_VECTOR 0xE30B //Command IDs from section 6.4, page 42 //These are used to calibrate, initialize, set orientation, tare etc the sensor #define COMMAND_ERRORS 1 #define COMMAND_COUNTER 2 #define COMMAND_TARE 3 #define COMMAND_INITIALIZE 4 #define COMMAND_DCD 6 #define COMMAND_ME_CALIBRATE 7 #define COMMAND_DCD_PERIOD_SAVE 9 #define COMMAND_OSCILLATOR 10 #define COMMAND_CLEAR_DCD 11 #define CALIBRATE_ACCEL 0 #define CALIBRATE_GYRO 1 #define CALIBRATE_MAG 2 #define CALIBRATE_PLANAR_ACCEL 3 #define CALIBRATE_ACCEL_GYRO_MAG 4 #define CALIBRATE_STOP 5 #define MAX_PACKET_SIZE 128 //Packets can be up to 32k but we don't have that much RAM. #define MAX_METADATA_SIZE 9 //This is in words. There can be many but we mostly only care about the first 9 (Qs, range, etc) class BNO080 { public: boolean begin(uint8_t deviceAddress = BNO080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire); //By default use the default I2C addres, and use Wire port void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. void softReset(); //Try to reset the IMU via software uint8_t resetReason(); //Query the IMU for the reason it last reset float qToFloat(int16_t fixedPointValue, uint8_t qPoint); //Given a Q value, converts fixed point floating to regular floating point number boolean waitForI2C(); //Delay based polling for I2C traffic boolean receivePacket(void); boolean getData(uint16_t bytesRemaining); //Given a number of bytes, send the requests in I2C_BUFFER_LENGTH chunks boolean sendPacket(uint8_t channelNumber, uint8_t dataLength); void printPacket(void); //Prints the current shtp header and data packets void enableRotationVector(uint16_t timeBetweenReports); void enableGameRotationVector(uint16_t timeBetweenReports); void enableAccelerometer(uint16_t timeBetweenReports); void enableLinearAccelerometer(uint16_t timeBetweenReports); void enableGyro(uint16_t timeBetweenReports); void enableMagnetometer(uint16_t timeBetweenReports); void enableStepCounter(uint16_t timeBetweenReports); void enableStabilityClassifier(uint16_t timeBetweenReports); void enableActivityClassifier(uint16_t timeBetweenReports, uint32_t activitiesToEnable, uint8_t (&activityConfidences)[9]); bool dataAvailable(void); void parseInputReport(void); float getQuatI(); float getQuatJ(); float getQuatK(); float getQuatReal(); float getQuatRadianAccuracy(); uint8_t getQuatAccuracy(); float getAccelX(); float getAccelY(); float getAccelZ(); uint8_t getAccelAccuracy(); float getLinAccelX(); float getLinAccelY(); float getLinAccelZ(); uint8_t getLinAccelAccuracy(); float getGyroX(); float getGyroY(); float getGyroZ(); uint8_t getGyroAccuracy(); float getMagX(); float getMagY(); float getMagZ(); uint8_t getMagAccuracy(); void calibrateAccelerometer(); void calibrateGyro(); void calibrateMagnetometer(); void calibratePlanarAccelerometer(); void calibrateAll(); void endCalibration(); void saveCalibration(); uint16_t getStepCount(); uint8_t getStabilityClassifier(); uint8_t getActivityClassifier(); void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports); void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig); void sendCommand(uint8_t command); void sendCalibrateCommand(uint8_t thingToCalibrate); //Metadata functions int16_t getQ1(uint16_t recordID); int16_t getQ2(uint16_t recordID); int16_t getQ3(uint16_t recordID); float getResolution(uint16_t recordID); float getRange(uint16_t recordID); uint32_t readFRSword(uint16_t recordID, uint8_t wordNumber); void frsReadRequest(uint16_t recordID, uint16_t readOffset, uint16_t blockSize); bool readFRSdata(uint16_t recordID, uint8_t startLocation, uint8_t wordsToRead); //Global Variables uint8_t shtpHeader[4]; //Each packet has a header of 4 bytes uint8_t shtpData[MAX_PACKET_SIZE]; uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0}; //There are 6 com channels. Each channel has its own seqnum uint8_t commandSequenceNumber = 0; //Commands have a seqNum as well. These are inside command packet, the header uses its own seqNum per channel uint32_t metaData[MAX_METADATA_SIZE]; //There is more than 10 words in a metadata record but we'll stop at Q point 3 private: //Variables TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware uint8_t _deviceAddress; //Keeps track of I2C address. setI2CAddress changes this. Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial. boolean _printDebug = false; //Flag to print debugging variables //These are the raw sensor values pulled from the user requested Input Report uint16_t rawAccelX, rawAccelY, rawAccelZ, accelAccuracy; uint16_t rawLinAccelX, rawLinAccelY, rawLinAccelZ, accelLinAccuracy; uint16_t rawGyroX, rawGyroY, rawGyroZ, gyroAccuracy; uint16_t rawMagX, rawMagY, rawMagZ, magAccuracy; uint16_t rawQuatI, rawQuatJ, rawQuatK, rawQuatReal, rawQuatRadianAccuracy, quatAccuracy; uint16_t stepCount; uint8_t stabilityClassifier; uint8_t activityClassifier; uint8_t *_activityConfidences; //Array that store the confidences of the 9 possible activities //These Q values are defined in the datasheet but can also be obtained by querying the meta data records //See the read metadata example for more info int16_t rotationVector_Q1 = 14; int16_t accelerometer_Q1 = 8; int16_t linear_accelerometer_Q1 = 8; int16_t gyro_Q1 = 9; int16_t magnetometer_Q1 = 4; }; 请根据以上参考代码,写出我所需的STM32F411ceu6基于I2C控制BNO080的库函数
07-23
51 // @VsrTest = VSR-3.2-001.001|VSR-3.2-001.002 52 TEST_F(VintfNoHidlTest, NoHidl) { 53 int apiLevel = android::base::GetIntProperty("ro.vendor.api_level", 0); 54 if (apiLevel < __ANDROID_API_U__) { 55 GTEST_SKIP() << "Not applicable to this device"; 56 return; 57 } 58 int maxNumberOfHidlHals; 59 std::set<std::string> halInterfaces; 60 if (apiLevel == __ANDROID_API_U__) { 61 maxNumberOfHidlHals = kMaxNumberOfHidlHalsU; 62 sp<hidl::manager::V1_0::IServiceManager> sm = 63 ::android::hardware::defaultServiceManager(); 64 ASSERT_NE(sm, nullptr); 65 hardware::Return<void> ret = 66 sm->list([&halInterfaces](const auto& interfaces) { 67 for (const auto& interface : interfaces) { 68 std::vector<std::string> splitInterface = 69 android::base::Split(interface, "@"); 70 ASSERT_GE(splitInterface.size(), 1); 71 // We only care about packages, since HIDL HALs typically need to 72 // include all of the older minor versions as well as the version 73 // they are implementing and we don't want to count those 74 halInterfaces.insert(splitInterface[0]); 75 } 76 }); 77 } else { 78 maxNumberOfHidlHals = 0; 79 halInterfaces = allHidlManifestInterfaces(); 80 } 81 if (halInterfaces.size() > maxNumberOfHidlHals) { 82 ADD_FAILURE() 83 << "There are " << halInterfaces.size() 84 << " HIDL interfaces served on the device. " 85 << "These must be converted to AIDL as part of HIDL's " 86 "deprecation processes.\n" 87 "NOTE: vts_treble_vintf_vendor_test should pass before this test. " 88 "Make sure the device under test is targeting " 89 "the correct Framework Compatibility Matrix with " 90 "target-level=\"202404\" or greater. That will cause " 91 "the framework/system HIDL services to stop being registered. " 92 "If those are still registered because the device is targeting " 93 "and older FCM, this test will fail."; 94 for (const auto& interface : halInterfaces) { 95 ADD_FAILURE() << interface << " registered as a HIDL interface " 96 << "but must be in AIDL"; 97 } 98 } 99 }
03-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值