diff --git a/F1-nolib/DS18/DS18.bin b/F1-nolib/DS18/DS18.bin index 1609d46..0430dfd 100755 Binary files a/F1-nolib/DS18/DS18.bin and b/F1-nolib/DS18/DS18.bin differ diff --git a/F1-nolib/DS18/ds18.c b/F1-nolib/DS18/ds18.c index a4ff4ad..05d6642 100644 --- a/F1-nolib/DS18/ds18.c +++ b/F1-nolib/DS18/ds18.c @@ -18,12 +18,15 @@ #include "ds18.h" #include "proto.h" - +#include "usb.h" //#define EBUG +// ID1: 0x28 0xba 0xc7 0xea 0x05 0x00 0x00 0xc2 +// ID2: 0x28 0x68 0xc9 0xe9 0x05 0x00 0x00 0x42 +// ID3: 0x28 0x23 0xef 0xe9 0x05 0x00 0x00 0xab + #ifdef EBUG -#include "usb.h" #define DBG(x) do{USB_send(x);}while(0) #else #define DBG(x) @@ -99,8 +102,8 @@ * 8 - CRC */ -// max amount of bits (1bytes x 8bits) -#define NmeasurementMax (88) +// max amount of bits (20bytes x 8bits) +#define NmeasurementMax (160) // reset pulse length (ms+1..2) #define DS18_RESETPULSE_LEN (3) // max length of measurement (ms+1..2) @@ -108,6 +111,8 @@ // maximal received data bytes #define IMAXCTR (10) +static uint8_t DS18ID[8] = {0}, matchID = 0; + static void (*ow_process_resdata)() = NULL; // what to do with received data static DS18_state dsstate = DS18_SLEEP; @@ -122,6 +127,25 @@ static uint8_t receivectr = 0; // data bytes amount to receive // prepare buffers to sending #define OW_reset_buffer() do{cc1buff_ctr = 0; receivectr = 0; totbytesctr = 0;}while(0) +// several devices on line +void DS18_setID(const uint8_t ID[8]){ + uint32_t *O = (uint32_t*)DS18ID, *I = (uint32_t*)ID; + *O++ = *I++; *O = *I; + matchID = 1; +#ifdef EBUG + USB_send("DS18_setID: "); + for(int i = 0; i < 8; ++i){ + USB_send(" 0x"); + printhex(DS18ID[i]); + } + USB_send("\n"); +#endif +} +// the only device on line +void DS18_clearID(){ + matchID = 0; +} + /** * add next data byte * @param ow_byte - byte to convert @@ -224,6 +248,22 @@ static void DS18_getReg(int n){ printsp(r, n); } +static int chkCRC(const uint8_t data[9]){ + uint8_t crc = 0; + for(int n = 0; n < 8; ++n){ + crc = crc ^ data[n]; + for(int i = 0; i < 8; i++){ + if(crc & 1) + crc = (crc >> 1) ^ 0x8C; + else + crc >>= 1; + } + } + //USB_send("got crc: "); printhex(crc); USB_send("\n"); + if(data[8] == crc) return 0; + return 1; +} + // data processing functions static void DS18_gettemp(){ // calculate T dsstate = DS18_SLEEP; @@ -238,6 +278,18 @@ static void DS18_gettemp(){ // calculate T dsstate = DS18_ERROR; return; } + int ctr; + for(ctr = 0; ctr < 9; ++ctr){ + if(r[ctr] != 0xff) break; + } + if(ctr == 9){ + USB_send("Target ID not found"); + return; + } + if(chkCRC(r)){ + USB_send("CRC is wrong\n"); + return; + } uint16_t l = r[0], m = r[1], v; int32_t t; if(r[4] == 0xff){ // DS18S20 @@ -256,7 +308,13 @@ static void DS18_pollt(){ // poll T if((r = OW_readbuf()) && receivectr == 1){ if(*r == CONVERSION_DONE){ OW_reset_buffer(); - OW_add_byte(OW_SKIP_ROM); + if(matchID){ // add MATCH command & target ID + OW_add_byte(OW_MATCH_ROM); + for(int i = 0; i < 8; ++i) + OW_add_byte(DS18ID[i]); + }else{ + OW_add_byte(OW_SKIP_ROM); + } OW_add_byte(OW_READ_SCRATCHPAD); OW_add_read_seq(9); ow_process_resdata = DS18_gettemp; diff --git a/F1-nolib/DS18/ds18.h b/F1-nolib/DS18/ds18.h index 7ab140e..56e1403 100644 --- a/F1-nolib/DS18/ds18.h +++ b/F1-nolib/DS18/ds18.h @@ -42,5 +42,8 @@ void DS18_process(uint32_t Tms); int DS18_readScratchpad(); void DS18_poll(); +void DS18_clearID(); +void DS18_setID(const uint8_t ID[8]); + #endif // DHT_H__ diff --git a/F1-nolib/DS18/proto.c b/F1-nolib/DS18/proto.c index d66614b..5ee884f 100644 --- a/F1-nolib/DS18/proto.c +++ b/F1-nolib/DS18/proto.c @@ -22,67 +22,237 @@ extern volatile uint32_t Tms; + +char *omit_spaces(const char *buf){ + while(*buf){ + if(*buf > ' ') break; + ++buf; + } + return (char*)buf; +} + +// In case of overflow return `buf` and N==0xffffffff +// read decimal number & return pointer to next non-number symbol +static char *getdec(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '9'){ + break; + } + if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow + *N = 0xffffff; + return start; + } + num *= 10; + num += c - '0'; + ++buf; + } + *N = num; + return (char*)buf; +} +// read hexadecimal number (without 0x prefix!) +static char *gethex(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + uint8_t M = 0; + if(c >= '0' && c <= '9'){ + M = '0'; + }else if(c >= 'A' && c <= 'F'){ + M = 'A' - 10; + }else if(c >= 'a' && c <= 'f'){ + M = 'a' - 10; + } + if(M){ + if(num & 0xf0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 4; + num += c - M; + }else{ + break; + } + ++buf; + } + *N = num; + return (char*)buf; +} +// read octal number (without 0 prefix!) +static char *getoct(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '7'){ + break; + } + if(num & 0xe0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 3; + num += c - '0'; + ++buf; + } + *N = num; + return (char*)buf; +} +// read binary number (without b prefix!) +static char *getbin(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '1'){ + break; + } + if(num & 0x80000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 1; + if(c == '1') num |= 1; + ++buf; + } + *N = num; + return (char*)buf; +} + +/** + * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111) + * @param buf - buffer with number and so on + * @param N - the number read + * @return pointer to first non-number symbol in buf + * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) + */ +char *getnum(const char *txt, uint32_t *N){ + char *nxt = NULL; + char *s = omit_spaces(txt); + if(*s == '0'){ // hex, oct or 0 + if(s[1] == 'x' || s[1] == 'X'){ // hex + nxt = gethex(s+2, N); + if(nxt == s+2) nxt = (char*)txt; + }else if(s[1] > '0'-1 && s[1] < '8'){ // oct + nxt = getoct(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ // 0 + nxt = s+1; + *N = 0; + } + }else if(*s == 'b' || *s == 'B'){ + nxt = getbin(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ + nxt = getdec(s, N); + if(nxt == s) nxt = (char*)txt; + } + return nxt; +} + static const char *helpmesg = + "'C' - clear match ROM\n" + "'D' - get DS18 state\n" "'I' - get DS18 ID\n" "'M' - start measurement\n" "'P' - read scratchpad\n" - "'S' - get DHT state\n" + "'S' - set match ROM (S 0xaa 0xbb... - 8 bytes of ID)\n" "'R' - software reset\n" "'T' - get time from start\n" "'W' - test watchdog\n" ; +// read 8 bytes of ROM and run SETROM +static void setROM(const char *buf){ + uint8_t ID[8]; + uint32_t N; + for(int i = 0; i < 8; ++i){ + char *nxt = getnum(buf, &N); + if(nxt == buf || N > 0xff){ + USB_send("Wrong data: "); + USB_send(buf); + return; + } + ID[i] = (uint8_t) N; + buf = nxt; + } + DS18_setID(ID); + USB_send("Set ID to:"); + for(int i = 0; i < 8; ++i){ + USB_send(" 0x"); + printhex(ID[i]); + } + USB_send("\n"); +} + const char *parse_cmd(const char *buf){ - if(buf[1] != '\n') return buf; - switch(*buf){ - case 'I': - if(DS18_readID()) return "Reading ID..\n"; - else return "Error\n"; - case 'M': - if(DS18_start()) return "Started\n"; - else return "Wait a little\n"; - break; -/* case 'p': - DS18_poll(); - return "polling\n"; - break;*/ - case 'P': - if(DS18_readScratchpad()) return "Reading scr..\n"; - else return "Error\n"; - break; - case 'R': - USB_send("Soft reset\n"); - NVIC_SystemReset(); - break; - case 'S': - switch(DS18_getstate()){ - case DS18_SLEEP: - return "Sleeping\n"; - case DS18_RESETTING: - return "Resetting\n"; - case DS18_DETECTING: - return "Detecting\n"; - case DS18_DETDONE: - return "Detection done\n"; - case DS18_READING: - return "Measuring\n"; - case DS18_GOTANSWER: - return "Results are ready\n"; - default: - return "Not found\n"; - } - case 'T': - USB_send("T="); - USB_send(u2str(Tms)); - USB_send("ms\n"); - break; - case 'W': - USB_send("Wait for reboot\n"); - while(1){nop();}; - break; - default: // help - return helpmesg; - break; + if(buf[1] == '\n'){ + switch(*buf){ + case 'C': + DS18_clearID(); + return "Don't send MATCH ROM\n"; + break; + case 'D': + switch(DS18_getstate()){ + case DS18_SLEEP: + return "Sleeping\n"; + case DS18_RESETTING: + return "Resetting\n"; + case DS18_DETECTING: + return "Detecting\n"; + case DS18_DETDONE: + return "Detection done\n"; + case DS18_READING: + return "Measuring\n"; + case DS18_GOTANSWER: + return "Results are ready\n"; + default: + return "Not found\n"; + } + break; + case 'I': + if(DS18_readID()) return "Reading ID..\n"; + else return "Error\n"; + case 'M': + if(DS18_start()) return "Started\n"; + else return "Wait a little\n"; + break; + /* case 'p': + DS18_poll(); + return "polling\n"; + break;*/ + case 'P': + if(DS18_readScratchpad()) return "Reading scr..\n"; + else return "Error\n"; + break; + case 'R': + USB_send("Soft reset\n"); + NVIC_SystemReset(); + break; + case 'T': + USB_send("T="); + USB_send(u2str(Tms)); + USB_send("ms\n"); + break; + case 'W': + USB_send("Wait for reboot\n"); + while(1){nop();}; + break; + default: // help + return helpmesg; + break; + } + }else{ // several letters + switch(*buf){ + case 'S': + setROM(buf + 1); + break; + default: + return buf; + } } return NULL; }