Tic Stepper Motor Controller library for Arduino
Tic.cpp
1 #include <Tic.h>
2 #include <Arduino.h>
3 
4 static const uint16_t Tic03aCurrentTable[33] =
5 {
6  0,
7  1,
8  174,
9  343,
10  495,
11  634,
12  762,
13  880,
14  990,
15  1092,
16  1189,
17  1281,
18  1368,
19  1452,
20  1532,
21  1611,
22  1687,
23  1762,
24  1835,
25  1909,
26  1982,
27  2056,
28  2131,
29  2207,
30  2285,
31  2366,
32  2451,
33  2540,
34  2634,
35  2734,
36  2843,
37  2962,
38  3093,
39 };
40 
41 void TicBase::setCurrentLimit(uint16_t limit)
42 {
43  uint8_t code = 0;
44 
45  if (product == TicProduct::T500)
46  {
47  for (uint8_t i = 0; i < 33; i++)
48  {
49  if (Tic03aCurrentTable[i] <= limit)
50  {
51  code = i;
52  }
53  else
54  {
55  break;
56  }
57  }
58  }
59  else if (product == TicProduct::T249)
60  {
61  code = limit / TicT249CurrentUnits;
62  }
63  else if (product == TicProduct::Tic36v4)
64  {
65  if (limit < 72) { code = 0; }
66  else if (limit >= 9095) { code = 127; }
67  else
68  {
69  code = ((uint32_t)limit * 768 - 55000 / 2) / 55000;
70  if (code < 127 && (((uint32_t)55000 * (code + 1) + 384) / 768) <= limit)
71  {
72  code++;
73  }
74  }
75  }
76  else
77  {
78  code = limit / TicCurrentUnits;
79  }
80 
81  commandW7(TicCommand::SetCurrentLimit, code);
82 }
83 
85 {
86  uint8_t code = getVar8(VarOffset::CurrentLimit);
87  if (product == TicProduct::T500)
88  {
89  if (code > 32) { code = 32; }
90  return Tic03aCurrentTable[code];
91  }
92  else if (product == TicProduct::T249)
93  {
94  return code * TicT249CurrentUnits;
95  }
96  else if (product == TicProduct::Tic36v4)
97  {
98  return ((uint32_t)55000 * code + 384) / 768;
99  }
100  else
101  {
102  return code * TicCurrentUnits;
103  }
104 }
105 
106 /**** TicSerial ****/
107 
108 void TicSerial::commandW32(TicCommand cmd, uint32_t val)
109 {
110  sendCommandHeader(cmd);
111 
112  // byte with MSbs:
113  // bit 0 = MSb of first (least significant) data byte
114  // bit 1 = MSb of second data byte
115  // bit 2 = MSb of third data byte
116  // bit 3 = MSb of fourth (most significant) data byte
117  serialW7(((val >> 7) & 1) |
118  ((val >> 14) & 2) |
119  ((val >> 21) & 4) |
120  ((val >> 28) & 8));
121 
122  serialW7(val >> 0); // least significant byte with MSb cleared
123  serialW7(val >> 8);
124  serialW7(val >> 16);
125  serialW7(val >> 24); // most significant byte with MSb cleared
126 
127  _lastError = 0;
128 }
129 
130 void TicSerial::commandW7(TicCommand cmd, uint8_t val)
131 {
132  sendCommandHeader(cmd);
133  serialW7(val);
134 
135  _lastError = 0;
136 }
137 
138 void TicSerial::getSegment(TicCommand cmd, uint8_t offset,
139  uint8_t length, void * buffer)
140 {
141  length &= 0x3F;
142  sendCommandHeader(cmd);
143  serialW7(offset & 0x7F);
144  serialW7(length | (offset >> 1 & 0x40));
145 
146  uint8_t byteCount = _stream->readBytes((uint8_t *)buffer, length);
147  if (byteCount != length)
148  {
149  _lastError = 50;
150 
151  // Set the buffer bytes to 0 so the program will not use an uninitialized
152  // variable.
153  memset(buffer, 0, length);
154  return;
155  }
156 
157  _lastError = 0;
158 }
159 
160 void TicSerial::sendCommandHeader(TicCommand cmd)
161 {
162  if (_deviceNumber == 255)
163  {
164  // Compact protocol
165  _stream->write((uint8_t)cmd);
166  }
167  else
168  {
169  // Pololu protocol
170  _stream->write(0xAA);
171  serialW7(_deviceNumber);
172  serialW7((uint8_t)cmd);
173  }
174  _lastError = 0;
175 }
176 
177 /**** TicI2C ****/
178 
179 void TicI2C::commandQuick(TicCommand cmd)
180 {
181  Wire.beginTransmission(_address);
182  Wire.write((uint8_t)cmd);
183  _lastError = Wire.endTransmission();
184 }
185 
186 void TicI2C::commandW32(TicCommand cmd, uint32_t val)
187 {
188  Wire.beginTransmission(_address);
189  Wire.write((uint8_t)cmd);
190  Wire.write(val >> 0); // lowest byte
191  Wire.write(val >> 8);
192  Wire.write(val >> 16);
193  Wire.write(val >> 24); // highest byte
194  _lastError = Wire.endTransmission();
195 }
196 
197 void TicI2C::commandW7(TicCommand cmd, uint8_t val)
198 {
199  Wire.beginTransmission(_address);
200  Wire.write((uint8_t)cmd);
201  Wire.write(val & 0x7F);
202  _lastError = Wire.endTransmission();
203 }
204 
205 void TicI2C::getSegment(TicCommand cmd, uint8_t offset,
206  uint8_t length, void * buffer)
207 {
208  Wire.beginTransmission(_address);
209  Wire.write((uint8_t)cmd);
210  Wire.write(offset);
211  _lastError = Wire.endTransmission(false); // no stop (repeated start)
212  if (_lastError)
213  {
214  // Set the buffer bytes to 0 so the program will not use an uninitialized
215  // variable.
216  memset(buffer, 0, length);
217  return;
218  }
219 
220  uint8_t byteCount = Wire.requestFrom(_address, (uint8_t)length);
221  if (byteCount != length)
222  {
223  _lastError = 50;
224  memset(buffer, 0, length);
225  return;
226  }
227 
228  _lastError = 0;
229  uint8_t * ptr = (uint8_t *)buffer;
230  for (uint8_t i = 0; i < length; i++)
231  {
232  *ptr = Wire.read();
233  ptr++;
234  }
235 }
void setCurrentLimit(uint16_t limit)
Definition: Tic.cpp:41
uint8_t _lastError
Definition: Tic.h:1281
const uint8_t TicT249CurrentUnits
Definition: Tic.h:34
const uint8_t TicCurrentUnits
Definition: Tic.h:30
uint16_t getCurrentLimit()
Definition: Tic.cpp:84
TicCommand
Definition: Tic.h:65