Ditch a bunch of superfluous lines that were always unused and made hex interpretatio...
[freeems-vanilla.git] / src / utils.c
blobad9bc2cf4b456834b028ca3d8a45ab5c9b0a9e75
1 /* FreeEMS - the open source engine management system
3 * Copyright 2008, 2009, 2010 Fred Cooke, Philip L Johnson
5 * This file is part of the FreeEMS project.
7 * FreeEMS software is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * FreeEMS software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with any FreeEMS software. If not, see http://www.gnu.org/licenses/
20 * We ask that if you make any changes to this file you email them upstream to
21 * us at admin(at)diyefi(dot)org or, even better, fork the code on github.com!
23 * Thank you for choosing FreeEMS to run your engine!
27 /** @file
29 * @brief Utility functions only
31 * General purpose utility functions that are used in various places throughout
32 * the code base. Functions should only be placed here if they are not strongly
33 * related to any other set of functionality.
35 * @author Fred Cooke
39 #define UTILS_C
40 #include "inc/freeEMS.h"
41 #include "inc/commsISRs.h"
42 #include "inc/utils.h"
43 #include <string.h>
46 /** @brief Add two unsigned shorts safely
48 * This will either return short max or the sum of the two arguments.
50 * @author Fred Cooke
52 * @param addend1
53 * @param addend2
55 unsigned short safeAdd(unsigned short addend1, unsigned short addend2){
56 if((SHORTMAX - addend1) > addend2){
57 return addend1 + addend2;
58 }else{
59 return SHORTMAX;
64 /** @brief Add signed short to an unsigned short safely
66 * This will either return short max, zero, or the sum of the two arguments.
68 * @author Fred Cooke
70 * @param addend1
71 * @param addend2
73 unsigned short safeTrim(unsigned short addend1, signed short addend2){
75 if(addend2 < 0){
76 if(addend1 > -addend2){
77 return addend1 + addend2;
78 }else{
79 return 0;
81 }else if(addend2 > 0){
82 if(addend2 < (SHORTMAX - addend1)){
83 return addend1 + addend2;
84 }else{
85 return SHORTMAX;
87 }else{
88 return addend1;
93 /** @brief Scale without overflow
95 * Takes a base value and a scaler where 0x8000/32768 means 100%, 0 means 0%
96 * and 0xFFFF/65535 means 200%, and returns the baseValue multiplied, in effect, by the
97 * resulting percentage figure.
99 * @author Fred Cooke
101 * @param baseValue
102 * @param dividend
103 * @param divisor
105 unsigned short safeScale(unsigned short baseValue, unsigned short dividend, unsigned short divisor){
106 /* Perform the scaling */
107 unsigned short scaled = ((unsigned long)baseValue * dividend) / divisor;
109 /* If the trim is greater than 100% then the trimmedPW MUST be larger */
110 /* If it's less than 100% it can't have overflowed. If it's not larger, it overflowed */
111 if((dividend > divisor) && (baseValue > scaled)){
112 return SHORTMAX;
113 }else{
114 return scaled;
119 /** @brief Setup tune switching
121 * Place the correct set of tables in RAM based on a boolean parameter
123 * @todo TODO change parameter style to be a pointer to a register and a mask?
125 * @author Fred Cooke
127 * @param bool which set of data to enable.
129 void setupPagedRAM(unsigned char bool){
130 if(bool){
131 currentFuelRPage = RPAGE_FUEL_ONE;
132 currentTimeRPage = RPAGE_TIME_ONE;
133 currentTuneRPage = RPAGE_TUNE_ONE;
134 }else{
135 currentFuelRPage = RPAGE_FUEL_TWO;
136 currentTimeRPage = RPAGE_TIME_TWO;
137 currentTuneRPage = RPAGE_TUNE_TWO;
140 RPAGE = currentTuneRPage;
144 /** @brief Demonstrate PWM
146 * Demonstrate basic PWM module usage by setting duty to scaled ADC inputs.
148 * @author Fred Cooke
150 void adjustPWM(){
151 PWMDTY0 = ATD0DR0 >> 2; // scale raw adc to a duty
152 PWMDTY1 = ATD0DR1 >> 2; // scale raw adc to a duty
153 PWMDTY2 = ATD0DR2 >> 2; // scale raw adc to a duty
154 PWMDTY3 = ATD0DR3 >> 2; // scale raw adc to a duty
155 PWMDTY4 = ATD0DR4 >> 2; // scale raw adc to a duty
156 PWMDTY5 = ATD0DR5 >> 2; // scale raw adc to a duty
157 PWMDTY6 = ATD0DR6 >> 2; // scale raw adc to a duty
158 PWMDTY7 = ATD0DR7 >> 2; // scale raw adc to a duty (user led instead at the moment, see init)
162 /** @brief Read ADCs one at a time
164 * Read ADCs into the correct bank one at a time by name.
166 * @author Fred Cooke
168 * @param Arrays a pointer to an ADCBuffer struct to store ADC values in.
170 void sampleEachADC(ADCBuffer *Arrays){
171 /* ATD0 */
172 Arrays->IAT = ATD0DR0;
173 Arrays->CHT = ATD0DR1;
174 Arrays->TPS = ATD0DR2;
175 Arrays->EGO = ATD0DR3;
176 Arrays->MAP = ATD0DR4;
177 Arrays->AAP = ATD0DR5;
178 Arrays->BRV = ATD0DR6;
179 Arrays->MAT = ATD0DR7;
181 /* ATD1 */
182 Arrays->EGO2 = ATD1DR0;
183 Arrays->IAP = ATD1DR1;
184 Arrays->MAF = ATD1DR2;
185 Arrays->SpareADC3 = ATD1DR3;
186 Arrays->SpareADC4 = ATD1DR4;
187 Arrays->SpareADC5 = ATD1DR5;
188 Arrays->SpareADC6 = ATD1DR6;
189 Arrays->SpareADC7 = ATD1DR7;
193 /** @brief Read ADCs in a loop
195 * Read ADCs into the correct bank in a loop using pointers.
197 * @author Fred Cooke
199 * @param Arrays a pointer to an ADCBuffer struct to store ADC values in.
201 void sampleLoopADC(ADCBuffer *Arrays){
202 // get the address of the ADC array
203 unsigned short addr = (unsigned short)Arrays;
205 //sendUS(addr);
206 unsigned char loop;
207 /* (value of((address of ADCBuffers struct) + (offset to start of bank(0 or half struct length)) + (offset to particular ADC (loopcounter * 4)) + (offset to correct element(0 or 2)))) =
208 * (value of((address of ARRAY block) + (loop counter * 2))) */
210 for(loop=0;loop<16;loop += 2){
211 /* Do the first block */
212 DVUSP(addr + loop) = DVUSP(ATD0_BASE + loop);
214 /* Do the second block */
215 DVUSP(addr + 16 + loop) = DVUSP(ATD1_BASE + loop);
216 /// @todo TODO this needs to be split into two loops one for the small block and one for the big one for the future chips.
221 /* @brief Read ADCs with memcpy()
223 * Read ADCs into the correct bank using two fixed calls to memcpy()
225 * @author Fred Cooke
227 * @param Arrays a pointer to an ADCBuffer struct to store ADC values in.
229 * @warning this will corrupt your comms if you use it... don't use it
230 * @bug this will corrupt your comms if you use it... don't use it
232 void sampleBlockADC(ADCBuffer *Arrays){
233 memcpy(Arrays, (void*)ATD0_BASE, 16);
234 memcpy(Arrays+16, (void*)ATD1_BASE, 16);
238 /** @brief Sleep for X milli seconds
240 * Run in a nested loop repeatedly for X milli seconds.
242 * @author Fred Cooke
244 * @param ms the number of milli seconds to kill
246 void sleep(unsigned short ms){
247 unsigned short j, k;
248 for(j=0;j<ms;j++){
249 for(k=0;k<5714;k++){
255 /** @brief Sleep for X micro seconds
257 * Run in a nested loop repeatedly for X micro seconds.
259 * @note Very approximate...
261 * @author Fred Cooke
263 * @param us the number of micro seconds to kill
265 void sleepMicro(unsigned short us){
266 unsigned short j, k;
267 for(j=0;j<us;j++){
268 for(k=0;k<6;k++){
274 /** @brief Simple checksum
276 * Generate a simple additive checksum for a block of data.
278 * @author Fred Cooke
280 * @param block a pointer to a memory region to checksum.
281 * @param length how large the memory region to checksum is.
283 * @return a simple additive checksum.
285 unsigned char checksum(unsigned char *block, unsigned short length){
286 unsigned char sum = 0;
287 while (length-- > 0){
288 sum += *block++;
290 return sum;
294 /** @brief Homebrew strcpy()
296 * strcpy() wouldn't compile for me for some reason so I wrote my own.
298 * @author Fred Cooke
300 * @param dest where to copy the null terminated string to.
301 * @param source where to copy the null terminated string from.
303 * @return the length of the string copied, including the zero byte terminator.
305 unsigned short stringCopy(unsigned char* dest, unsigned char* source){
306 unsigned short length = 0;
307 do {
308 *dest++ = *source++;
309 length++;
310 } while(*(source-1) != 0);
311 return length;
315 * @returns a one based index of the failure point
317 * @note this will return a positive result with bad data in the last position of a maximum sized block
319 unsigned short compare(unsigned char* original, unsigned char* toCheck, unsigned short length){
320 unsigned short i;
321 for(i=0;i<length;i++){
322 if(original[i] != toCheck[i]){
323 return i + 1; // zero = success
326 return 0;