Manages the 1-wire bus

Dependents:   oldheating heating

Committer:
andrewboyson
Date:
Thu Feb 18 16:47:12 2021 +0000
Revision:
11:3859fee99d5d
Parent:
1:c272b1fcc834
Added 'value not set' to the list of possible values.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 0:b4b170ce93a4 1 #include <stdint.h>
andrewboyson 0:b4b170ce93a4 2 #include <stdbool.h>
andrewboyson 0:b4b170ce93a4 3
andrewboyson 0:b4b170ce93a4 4 #include "1-wire.h"
andrewboyson 0:b4b170ce93a4 5 #include "log.h"
andrewboyson 0:b4b170ce93a4 6 #include "1-wire-device.h"
andrewboyson 0:b4b170ce93a4 7 #include "ds18b20.h"
andrewboyson 0:b4b170ce93a4 8 #include "hrtimer.h"
andrewboyson 0:b4b170ce93a4 9
andrewboyson 0:b4b170ce93a4 10 #define SEND_BUFFER_LENGTH 10
andrewboyson 0:b4b170ce93a4 11 #define RECV_BUFFER_LENGTH 10
andrewboyson 0:b4b170ce93a4 12 static char send[SEND_BUFFER_LENGTH];
andrewboyson 0:b4b170ce93a4 13 static char recv[RECV_BUFFER_LENGTH];
andrewboyson 0:b4b170ce93a4 14 static int sendlen = 0;
andrewboyson 0:b4b170ce93a4 15 static int recvlen = 0;
andrewboyson 0:b4b170ce93a4 16
andrewboyson 0:b4b170ce93a4 17 int DeviceScanMs = 0;
andrewboyson 0:b4b170ce93a4 18 int DeviceCount = 0;
andrewboyson 0:b4b170ce93a4 19 char DeviceList[DEVICE_MAX * 8];
andrewboyson 0:b4b170ce93a4 20 char* DeviceAddress(int device)
andrewboyson 0:b4b170ce93a4 21 {
andrewboyson 0:b4b170ce93a4 22 return DeviceList + device * 8;
andrewboyson 0:b4b170ce93a4 23 }
andrewboyson 0:b4b170ce93a4 24 void DeviceAddressToString(char* pAddress, char* pText)
andrewboyson 0:b4b170ce93a4 25 {
andrewboyson 0:b4b170ce93a4 26 char *pAddressAfter = pAddress + 8;
andrewboyson 0:b4b170ce93a4 27 for (char* p = pAddress; p < pAddressAfter; p++)
andrewboyson 0:b4b170ce93a4 28 {
andrewboyson 0:b4b170ce93a4 29 char highnibble = *p >> 4; //Unsigned so fills with zeros
andrewboyson 0:b4b170ce93a4 30 char lownibble = *p & 0xF;
andrewboyson 0:b4b170ce93a4 31 *pText++ = highnibble < 0xA ? highnibble + '0' : highnibble - 0xA + 'A'; //Replace high nibble with its ascii equivalent
andrewboyson 0:b4b170ce93a4 32 *pText++ = lownibble < 0xA ? lownibble + '0' : lownibble - 0xA + 'A'; //Replace low nibble with its ascii equivalent
andrewboyson 0:b4b170ce93a4 33 *pText++ = p < pAddressAfter - 1 ? ' ' : 0; //Put in a space between the bytes or a NUL at the end of the last one
andrewboyson 0:b4b170ce93a4 34 }
andrewboyson 0:b4b170ce93a4 35 }
andrewboyson 0:b4b170ce93a4 36 void DeviceParseAddress(char* pText, char *pAddress)
andrewboyson 0:b4b170ce93a4 37 {
andrewboyson 0:b4b170ce93a4 38 int highNibble = 1;
andrewboyson 0:b4b170ce93a4 39 char *pAddressAfter = pAddress + 8;
andrewboyson 0:b4b170ce93a4 40 while(*pText && pAddress < pAddressAfter)
andrewboyson 0:b4b170ce93a4 41 {
andrewboyson 0:b4b170ce93a4 42 int nibble = -1;
andrewboyson 0:b4b170ce93a4 43 if (*pText >= '0' && *pText <= '9') nibble = *pText - '0';
andrewboyson 0:b4b170ce93a4 44 if (*pText >= 'A' && *pText <= 'F') nibble = *pText - 'A' + 0xA;
andrewboyson 0:b4b170ce93a4 45 if (*pText >= 'a' && *pText <= 'f') nibble = *pText - 'a' + 0xA;
andrewboyson 0:b4b170ce93a4 46 if (nibble >= 0) //Ignore characters which do not represent a hex number
andrewboyson 0:b4b170ce93a4 47 {
andrewboyson 0:b4b170ce93a4 48 if (highNibble)
andrewboyson 0:b4b170ce93a4 49 {
andrewboyson 0:b4b170ce93a4 50 *pAddress = nibble << 4; //Set the high nibble of the current address byte and zero the low nibble
andrewboyson 0:b4b170ce93a4 51 highNibble = 0; //Move onto the low nibble of this address byte
andrewboyson 0:b4b170ce93a4 52 }
andrewboyson 0:b4b170ce93a4 53 else //low nibble
andrewboyson 0:b4b170ce93a4 54 {
andrewboyson 0:b4b170ce93a4 55 *pAddress += nibble; //Add the low nibble to the current address byte
andrewboyson 0:b4b170ce93a4 56 highNibble = 1; //Move onto the high nibble of the next address byte
andrewboyson 0:b4b170ce93a4 57 pAddress++;
andrewboyson 0:b4b170ce93a4 58 }
andrewboyson 0:b4b170ce93a4 59 }
andrewboyson 0:b4b170ce93a4 60 pText++;
andrewboyson 0:b4b170ce93a4 61 }
andrewboyson 0:b4b170ce93a4 62 while (pAddress < pAddressAfter) *pAddress++ = 0; //Set any remaining bytes to zero
andrewboyson 0:b4b170ce93a4 63 }
andrewboyson 0:b4b170ce93a4 64
andrewboyson 0:b4b170ce93a4 65 char rom[8];
andrewboyson 0:b4b170ce93a4 66 bool allRomsFound = false;
andrewboyson 0:b4b170ce93a4 67 static void searchRom(int first)
andrewboyson 0:b4b170ce93a4 68 {
andrewboyson 0:b4b170ce93a4 69 sendlen = 1;
andrewboyson 0:b4b170ce93a4 70 send[0] = 0xF0; //Search Rom
andrewboyson 0:b4b170ce93a4 71 recvlen = 0;
andrewboyson 0:b4b170ce93a4 72 for (int i = 0; i < recvlen; i++) recv[i] = 0;
andrewboyson 0:b4b170ce93a4 73 if (first) OneWireSearch(send[0], rom, &allRomsFound);
andrewboyson 0:b4b170ce93a4 74 else OneWireSearch(send[0], NULL, NULL);
andrewboyson 0:b4b170ce93a4 75 }
andrewboyson 0:b4b170ce93a4 76 static void readScratchpad(int device)
andrewboyson 0:b4b170ce93a4 77 {
andrewboyson 0:b4b170ce93a4 78 sendlen = 10;
andrewboyson 0:b4b170ce93a4 79 send[0] = 0x55; //Match Rom
andrewboyson 0:b4b170ce93a4 80 for (int i = 0; i < 8; i++) send[i+1] = DeviceList[device * 8 + i];
andrewboyson 0:b4b170ce93a4 81 send[9] = 0xBE; //Read Scratchpad
andrewboyson 0:b4b170ce93a4 82 recvlen = 9;
andrewboyson 0:b4b170ce93a4 83 for (int i = 0; i < recvlen; i++) recv[i] = 0;
andrewboyson 0:b4b170ce93a4 84 OneWireExchange(sendlen, recvlen, send, recv, 0);
andrewboyson 0:b4b170ce93a4 85 }
andrewboyson 0:b4b170ce93a4 86 static void convertT()
andrewboyson 0:b4b170ce93a4 87 {
andrewboyson 0:b4b170ce93a4 88 sendlen = 2;
andrewboyson 0:b4b170ce93a4 89 send[0] = 0xCC; //Skip Rom
andrewboyson 0:b4b170ce93a4 90 send[1] = 0x44; //Convert T
andrewboyson 0:b4b170ce93a4 91 recvlen = 0;
andrewboyson 0:b4b170ce93a4 92 for (int i = 0; i < recvlen; i++) recv[i] = 0;
andrewboyson 0:b4b170ce93a4 93 OneWireExchange(sendlen, recvlen, send, recv, 750);
andrewboyson 0:b4b170ce93a4 94 }
andrewboyson 0:b4b170ce93a4 95 enum {
andrewboyson 0:b4b170ce93a4 96 IDLE,
andrewboyson 0:b4b170ce93a4 97 LIST_FIRST_DEVICE,
andrewboyson 0:b4b170ce93a4 98 LIST_NEXT_DEVICE,
andrewboyson 0:b4b170ce93a4 99 LIST_DEVICE_CHECK,
andrewboyson 0:b4b170ce93a4 100 CONVERT_T,
andrewboyson 0:b4b170ce93a4 101 CONVERT_T_CHECK,
andrewboyson 0:b4b170ce93a4 102 ENUMERATE_START,
andrewboyson 0:b4b170ce93a4 103 ENUMERATE,
andrewboyson 0:b4b170ce93a4 104 READ_SCRATCHPAD,
andrewboyson 0:b4b170ce93a4 105 EXTRACT_TEMPERATURE
andrewboyson 0:b4b170ce93a4 106 };
andrewboyson 0:b4b170ce93a4 107 static volatile int state = IDLE;
andrewboyson 0:b4b170ce93a4 108 bool DeviceBusy() { return state; }
andrewboyson 0:b4b170ce93a4 109 static void establishDeviceScanMs()
andrewboyson 0:b4b170ce93a4 110 {
andrewboyson 0:b4b170ce93a4 111
andrewboyson 0:b4b170ce93a4 112 //Get the scan time in counts and stop if it's the first one
andrewboyson 0:b4b170ce93a4 113 static uint32_t scanTimer = 0;
andrewboyson 0:b4b170ce93a4 114 bool firstScan = !scanTimer;
andrewboyson 0:b4b170ce93a4 115 uint32_t elapsed = HrTimerSinceRepetitive(&scanTimer);
andrewboyson 0:b4b170ce93a4 116 if (firstScan) return;
andrewboyson 0:b4b170ce93a4 117
andrewboyson 0:b4b170ce93a4 118 //Calculate the scan time in ms and record the scan time for the next pass
andrewboyson 0:b4b170ce93a4 119 int scanMs = elapsed / 96000;
andrewboyson 0:b4b170ce93a4 120
andrewboyson 0:b4b170ce93a4 121 //Calculate the difference beween this scan time and the average and update the average
andrewboyson 0:b4b170ce93a4 122 int diffMs = scanMs - DeviceScanMs;
andrewboyson 0:b4b170ce93a4 123 if (diffMs > 0xF || diffMs < 0xF)
andrewboyson 0:b4b170ce93a4 124 {
andrewboyson 0:b4b170ce93a4 125 DeviceScanMs += (scanMs - DeviceScanMs) >> 4;
andrewboyson 0:b4b170ce93a4 126 }
andrewboyson 0:b4b170ce93a4 127 else
andrewboyson 0:b4b170ce93a4 128 {
andrewboyson 0:b4b170ce93a4 129 if (scanMs > DeviceScanMs) DeviceScanMs++;
andrewboyson 0:b4b170ce93a4 130 if (scanMs < DeviceScanMs) DeviceScanMs--;
andrewboyson 0:b4b170ce93a4 131 }
andrewboyson 0:b4b170ce93a4 132 }
andrewboyson 0:b4b170ce93a4 133 static int handlestate()
andrewboyson 0:b4b170ce93a4 134 {
andrewboyson 0:b4b170ce93a4 135 if (OneWireBusy()) return 0;
andrewboyson 0:b4b170ce93a4 136 static int device;
andrewboyson 0:b4b170ce93a4 137 switch (state)
andrewboyson 0:b4b170ce93a4 138 {
andrewboyson 0:b4b170ce93a4 139 case IDLE:
andrewboyson 0:b4b170ce93a4 140 establishDeviceScanMs();
andrewboyson 0:b4b170ce93a4 141 state = LIST_FIRST_DEVICE;
andrewboyson 0:b4b170ce93a4 142 break;
andrewboyson 0:b4b170ce93a4 143
andrewboyson 0:b4b170ce93a4 144 case LIST_FIRST_DEVICE:
andrewboyson 0:b4b170ce93a4 145 device = 0;
andrewboyson 0:b4b170ce93a4 146 searchRom(1);
andrewboyson 0:b4b170ce93a4 147 state = LIST_DEVICE_CHECK;
andrewboyson 0:b4b170ce93a4 148 break;
andrewboyson 0:b4b170ce93a4 149 case LIST_DEVICE_CHECK:
andrewboyson 0:b4b170ce93a4 150 if (OneWireResult()) state = IDLE;
andrewboyson 0:b4b170ce93a4 151 else state = LIST_NEXT_DEVICE;
andrewboyson 0:b4b170ce93a4 152 break;
andrewboyson 0:b4b170ce93a4 153 case LIST_NEXT_DEVICE:
andrewboyson 0:b4b170ce93a4 154 for (int i = 0; i < 8; i++) DeviceList[8 * device + i] = rom[i];
andrewboyson 0:b4b170ce93a4 155 device++;
andrewboyson 0:b4b170ce93a4 156 if (allRomsFound || device >= DEVICE_MAX)
andrewboyson 0:b4b170ce93a4 157 {
andrewboyson 0:b4b170ce93a4 158 DeviceCount = device;
andrewboyson 0:b4b170ce93a4 159 state = CONVERT_T;
andrewboyson 0:b4b170ce93a4 160 }
andrewboyson 0:b4b170ce93a4 161 else
andrewboyson 0:b4b170ce93a4 162 {
andrewboyson 0:b4b170ce93a4 163 searchRom(0);
andrewboyson 0:b4b170ce93a4 164 state = LIST_DEVICE_CHECK;
andrewboyson 0:b4b170ce93a4 165 }
andrewboyson 0:b4b170ce93a4 166 break;
andrewboyson 0:b4b170ce93a4 167
andrewboyson 0:b4b170ce93a4 168 case CONVERT_T:
andrewboyson 0:b4b170ce93a4 169 convertT();
andrewboyson 0:b4b170ce93a4 170 state = CONVERT_T_CHECK;
andrewboyson 0:b4b170ce93a4 171 break;
andrewboyson 0:b4b170ce93a4 172 case CONVERT_T_CHECK:
andrewboyson 0:b4b170ce93a4 173 if (OneWireResult()) state = IDLE;
andrewboyson 0:b4b170ce93a4 174 else state = ENUMERATE_START;
andrewboyson 0:b4b170ce93a4 175 break;
andrewboyson 0:b4b170ce93a4 176
andrewboyson 0:b4b170ce93a4 177 case ENUMERATE_START:
andrewboyson 0:b4b170ce93a4 178 device = -1;
andrewboyson 0:b4b170ce93a4 179 state = ENUMERATE;
andrewboyson 0:b4b170ce93a4 180 break;
andrewboyson 0:b4b170ce93a4 181 case ENUMERATE:
andrewboyson 0:b4b170ce93a4 182 device++;
andrewboyson 0:b4b170ce93a4 183 if (device >= DeviceCount) state = IDLE;
andrewboyson 0:b4b170ce93a4 184 else if (DeviceList[device * 8] == DS18B20_FAMILY_CODE) state = READ_SCRATCHPAD;
andrewboyson 0:b4b170ce93a4 185 else state = ENUMERATE;
andrewboyson 0:b4b170ce93a4 186 break;
andrewboyson 0:b4b170ce93a4 187
andrewboyson 0:b4b170ce93a4 188 case READ_SCRATCHPAD:
andrewboyson 0:b4b170ce93a4 189 readScratchpad(device);
andrewboyson 0:b4b170ce93a4 190 state = EXTRACT_TEMPERATURE;
andrewboyson 0:b4b170ce93a4 191 break;
andrewboyson 0:b4b170ce93a4 192 case EXTRACT_TEMPERATURE:
andrewboyson 0:b4b170ce93a4 193 DS18B20ReadValue(OneWireResult(), device, recv[0], recv[1]);
andrewboyson 0:b4b170ce93a4 194 state = ENUMERATE;
andrewboyson 0:b4b170ce93a4 195 break;
andrewboyson 0:b4b170ce93a4 196
andrewboyson 0:b4b170ce93a4 197 default:
andrewboyson 0:b4b170ce93a4 198 LogF("Unknown DS18B20 state %d\r\n", state);
andrewboyson 0:b4b170ce93a4 199 return -1;
andrewboyson 0:b4b170ce93a4 200 }
andrewboyson 0:b4b170ce93a4 201 return 0;
andrewboyson 0:b4b170ce93a4 202 }
andrewboyson 0:b4b170ce93a4 203 static void logcomms()
andrewboyson 0:b4b170ce93a4 204 {
andrewboyson 0:b4b170ce93a4 205 static int wasbusy = 0;
andrewboyson 0:b4b170ce93a4 206 if (!OneWireBusy() && wasbusy)
andrewboyson 0:b4b170ce93a4 207 {
andrewboyson 0:b4b170ce93a4 208 LogF("1-wire | send:");
andrewboyson 0:b4b170ce93a4 209 for (int i = 0; i < sendlen; i++) LogF(" %02x", send[i]);
andrewboyson 0:b4b170ce93a4 210 LogF(" | recv:");
andrewboyson 0:b4b170ce93a4 211 for (int i = 0; i < recvlen; i++) LogF(" %02x", recv[i]);
andrewboyson 0:b4b170ce93a4 212 LogF("\r\n");
andrewboyson 0:b4b170ce93a4 213 }
andrewboyson 0:b4b170ce93a4 214 wasbusy = OneWireBusy();
andrewboyson 0:b4b170ce93a4 215 }
andrewboyson 0:b4b170ce93a4 216 void DeviceInit()
andrewboyson 0:b4b170ce93a4 217 {
andrewboyson 0:b4b170ce93a4 218 DS18B20Init();
andrewboyson 0:b4b170ce93a4 219 }
andrewboyson 0:b4b170ce93a4 220 int DeviceMain()
andrewboyson 0:b4b170ce93a4 221 {
andrewboyson 0:b4b170ce93a4 222
andrewboyson 0:b4b170ce93a4 223 if (OneWireTrace) logcomms();
andrewboyson 0:b4b170ce93a4 224
andrewboyson 0:b4b170ce93a4 225 int r = handlestate(); if (r) return -1;
andrewboyson 0:b4b170ce93a4 226
andrewboyson 0:b4b170ce93a4 227 return 0;
andrewboyson 0:b4b170ce93a4 228 }