From 47fb3dfb5b5d16377697d97541a4c94d1f28ebd4 Mon Sep 17 00:00:00 2001 From: Gergő J. Miklós Date: Tue, 6 Aug 2019 08:52:22 +0200 Subject: qmc5883 initial --- src/qmc5883.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/qmc5883.h | 12 ++ 2 files changed, 373 insertions(+) create mode 100644 src/qmc5883.c create mode 100644 src/qmc5883.h diff --git a/src/qmc5883.c b/src/qmc5883.c new file mode 100644 index 0000000..7bcab37 --- /dev/null +++ b/src/qmc5883.c @@ -0,0 +1,361 @@ + +#include +#include +#include +#include //#usleep +#include +#include //# isdigit() + + +#include "qmc5883.h" +#include "deftypes.h" + + +extern void bus_err(int ern); +extern void print_help(void); +extern uchar *xchg_data (uchar *buf, uint8 wrlen, uint8 waitlen, uint8 rdlen); + +unsigned char buf[32]; + + +void qmc5883_print_all(const uchar *opts) +{ + printf( + "00: Temperature data [°C] (reg: 0x00)\n" + "01: Configuration [hex] (reg: 0x01)\n" + "02: Tos (Overtemp) [°C] (reg: 0x03)\n" + "03: Thys (Hysteresis) [°C] (reg: 0x04)\n" + "\n"); +} + +void qmc5883_read_all(const uchar *opts) {} +// void hmc5883_read_one(const uchar *opts) {} +// void hmc5883_conf_set(const uchar *opts){} + + + + +static float calc_field(char direction, float gain){ // Calculate temperature + uint16 raw = 0; //# Signed by default + + // if(direction == 'x'){ + // buf[0] = 0x03; //# Measurement in the REG[0] + // } else if (direction == 'y'){ + // buf[0] = 0x07; + // } else if(direction == 'z'){ + // buf[0] = 0x05; + // } + + // buf[0] = 0x3d; + // buf[0] = 0x00; + // xchg_data(buf,1,0,3); + +// buf[0] = 0x3c; +// for(int i=0; i<15; i++){ +// buf[i] = 0xFF; +// } +// xchg_data(buf,14,0,14); + + // buf[0] = 0x01; + // xchg_data(buf,1,0,1); + + + buf[0] = 0x0A; + buf[1] = 0b10000000; //soft reset to all + xchg_data(buf,2,0,1); + + buf[0] = 0x09; + buf[1] = 0x15; + buf[2] = 0x0A; + buf[3] = 0b00000000; + buf[4] = 0x1b; + buf[5] = 0x01; + xchg_data(buf,6,2,1); + + + buf[0] = 0x00; + xchg_data(buf,1,0,14); + + // buf[0] = 0x3c; + // buf[1] = 0x01; + // buf[3] = 0xA0; + // xchg_data(buf,3,0,1); + + // buf[0] = 0x3c; + // buf[1] = 0x02; + // buf[2] = 0x00; + // xchg_data(buf,3,0,1); + + raw = buf[0] + buf[1]*256 ; //# /x*256 == x << 8/ (>> 5): Temp is 11bit data register + +// return(raw * 1.0); + + if((raw & 0x8000) == 0x8000){ //# check if the msb(bit11) is 1 (1024 = 0x400), 2'complement negative number + raw = ~raw + 1; //# 2'complement data + //raw = raw & 0xFFFF; //# Only the lowest 11bit needed + return( -1 * raw * (1.0/3000.0)); + } else { + return(raw *(1.0/3000.0)); //# 11bit -> 0.125°C or 9bit -> 0.5°C + } + +} + + +static float read_tos(void){ // Over-Temperature Shutdown register + uint16 rawtemp = 0; //# Int16 default signed + buf[0] = 0x03; //# Tos = REG[2] + xchg_data(buf,1,0,2); + + rawtemp = buf[0]*256 + buf[1]; // x*256 == x << 8 + rawtemp = (rawtemp) >> 7; //# 9bit data + + if((rawtemp & 0x100) == 0x100){ //# check MSB if it's a 2'complement number + rawtemp = ~rawtemp + 1 ; //# 2'complement, 2^9 = 512; + rawtemp = rawtemp & 0x1FF; //# lowest 9 bit + return (-1 * rawtemp * 0.5); + } else { + return (rawtemp * 0.5); //# 9bit -> 0.5 celsius + } +} + + + + +static uchar read_conf(void){ //Configuration register + buf[0] = 0x01; + xchg_data(buf,1,0,1); + return buf[0]; +} + + +// void lm75_read_all(const uchar *opts){ // Print out whole device's data +// // if(opts != NULL) +// // { +// // printf("00:%f\n", calc_temp(strtof(opts, NULL))); +// // } else { +// fprintf(stdout, "00:%f\n", calc_temp(0.0)); +// // } +// fprintf(stdout, "01:0x%x\n", read_conf()); +// fprintf(stdout, "02:%f\n", read_thys()); +// fprintf(stdout, "03:%f\n", read_tos()); + +// } + + +void qmc5883_read_one(const uchar *opts){ // Prints the selected register's data + uint16 id,i; + uchar temp[256]; + + if(opts != NULL){ //# Search the comma: ...<01,-11.24> + for(i = 0; i < strlen((char*)opts); i++){ + + if (*(opts+i) == ','){ + break; + + } else { + if( !isdigit(*(opts+i)) ){ //# Check the register string + fprintf(stderr, "The Register address must be an integer!\n"); + print_help(); + qmc5883_print_all(NULL); + exit (EXIT_FAILURE); + } + temp[i] = *(opts+i); //# copy register string + temp[i+1] = '\0'; + } + } + + id = atoi((char*)temp); //# Convert register to number + strncpy((char*)temp, (char*)opts+i+1, 255); //# Copy remain to temp + + switch (id) //# Which register is selected? + { + case 0x00: + // for(uint32 i=0; i<0xFFFFFFFF; i++){ + fprintf(stdout, "%f\n", calc_field(*temp, 0.73)); //# with the offset + // usleep(100*1000); + // } + break; + case 0x01: + fprintf(stdout, "0x%x\n", read_conf()); + break; + case 0x02: + + break; + case 0x03: + fprintf(stdout, "%f\n", read_tos()); + break; + default: + print_help(); + } + } +} + + + +void qmc5883_conf_set(const uchar *opts){ // Prints the selected register's data + uint16 i; + uchar temp[256]; + + if(opts != NULL){ + for(i = 0; i < strlen((char*)opts); i++){ + if (*(opts+i) == ','){ //# .... conf_set 0x49 thys,-10.5 + break; + } + temp[i] = *(opts+i); + temp[i+1] = '\0'; + } + + + if(!strcmp("tos", (char*)temp)){ //# Set the Tos register value + float inp; + uint16 temp; + buf[0] = 0x03; + inp = atof( (char*)(opts+i+1)); + + if(inp < 0){ + temp = 0 - inp/0.5; + temp = ~temp +1; //# 2'complement + buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) + buf[2] = ((temp << 7) | 0x7F) & 0xFF; //# |d8,d7,d6,d5|d4,d3,d2,d1|d0,xx,xx,xx|xx,xx,xx,xx| + } else { + temp = inp/0.5; + buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) + buf[2] = (temp << 7) & 0xFF;; + } + xchg_data(buf,3,0,2); + + + }else if(!strcmp("thys", (char*)temp)){ //# Set the Thys reg + float inp; + uint16 temp; + buf[0] = 0x02; + inp = atof( (char*)(opts+i+1)); + + if(inp < 0){ + temp = 0 - inp/0.5; + temp = ~temp +1; //# 2'complement + buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) + buf[2] = ((temp << 7) | 0x7F) & 0xFF; //# |d8,d7,d6,d5|d4,d3,d2,d1|d0,xx,xx,xx|xx,xx,xx,xx| + } else { + temp = inp/0.5; + buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) + buf[2] = (temp << 7) & 0xFF;; + } + xchg_data(buf,3,0,2); + + + }else if(!strcmp("conf", (char*)temp)){ //# Set whole conf register + + buf[0] = 0x01; + buf[1] = strtol((char*)(opts+i+1),NULL,0); + xchg_data(buf,2,0,1); + + + }else if(!strcmp("sleep", (char*)temp)){ //# Send the sleep command + + buf[0] = 0x01; + xchg_data(buf,1,0,1); + if (!strcmp("on",(char*)opts+i+1)) + { + buf[1] = buf[0] | 0x01; + } + else if(!strcmp("off",(char*)opts+i+1)) + { + // buf[1] = ~buf[0]; //# XOR = NEG->OR->NEG + // buf[1] = buf[1] | 0b00000001; //# Invert->add->invert + // buf[1] = ~buf[1]; + buf[1] = buf[0] ^ 0b00000001; //# XOR to clear the bit + } + else + { + qmc5883_print_all(NULL); + exit(EXIT_FAILURE); + } + buf[0] = 0x01; + xchg_data(buf,2,0,1); + + + }else if(!strcmp("mode", (char*)temp)){ //# Comparator/Interrupt mode + + buf[0] = 0x01; + xchg_data(buf,1,0,1); + if (!strcmp("comp",(char*)opts+i+1)) + { + buf[1] = buf[0] ^ 0b00000010; //# XOR to clear + } + else if(!strcmp("int",(char*)opts+i+1)) + { + buf[1] = buf[0] | 0b00000010; + } + else + { + qmc5883_print_all(NULL); + exit(EXIT_FAILURE); + } + buf[0] = 0x01; + xchg_data(buf,2,0,1); + + + }else if(!strcmp("tos_pol", (char*)temp)){ //# Tos polarity + + buf[0] = 0x01; + xchg_data(buf,1,0,1); + if (!strcmp("Al",(char*)opts+i+1)) + { + buf[1] = buf[0] ^ 0b00000100; //# XOR to clear the bit + } + else if(!strcmp("Ah",(char*)opts+i+1)) + { + buf[1] = buf[0] | 0b00000100; + } + else + { + qmc5883_print_all(NULL); + exit(EXIT_FAILURE); + } + buf[0] = 0x01; + xchg_data(buf,2,0,1); + + + }else if(!strcmp("fault_q", (char*)temp)){ //# Tos Fault Queue + + buf[0] = 0x01; + xchg_data(buf,1,0,1); + if (!strcmp("1",(char*)opts+i+1)) + { + buf[1] = buf[0] | 0b00011000; //# Add and clear whole section + buf[1] = buf[1] ^ 0b00011000; + } + else if(!strcmp("2",(char*)opts+i+1)) + { + buf[1] = buf[0] | 0b00011000; //# Clear first + buf[1] = buf[1] ^ 0b00011000; //# Clear first + buf[1] = buf[1] | 0b00001000; //# Set + } + else if(!strcmp("4",(char*)opts+i+1)) + { + buf[1] = buf[0] | 0b00011000; //# Clear first + buf[1] = buf[1] ^ 0b00011000; //# Clear first + buf[1] = buf[1] | 0b00010000; //# Set + } + else + { + qmc5883_print_all(NULL); + exit(EXIT_FAILURE); + } + buf[0] = 0x01; + xchg_data(buf,2,0,1); + + + } else { + // for(i = 0; i < strlen((char*)opts); i++ ){ + // if( !isxdigit(*(opts+i)) || *(opts+i) !='x' || opts[i] != ','){ //# Check the register string + // printf("The Register address, and value must be a hex, or an integer!\n"); + print_help(); + qmc5883_print_all(NULL); + exit (EXIT_FAILURE); + // } + // } + } + } +} \ No newline at end of file diff --git a/src/qmc5883.h b/src/qmc5883.h new file mode 100644 index 0000000..9d82b96 --- /dev/null +++ b/src/qmc5883.h @@ -0,0 +1,12 @@ + +#ifndef _HMC5883_INCLUDED +#define _HMC5883_INCLUDED + +#include "deftypes.h" + +void qmc5883_print_all(const uchar *opts); +void qmc5883_read_all(const uchar *opts); +void qmc5883_read_one(const uchar *opts); +void qmc5883_conf_set(const uchar *opts); + +#endif \ No newline at end of file -- cgit v1.2.3