Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
- http://pymbed.appspot.com/
- https://code.google.com/p/python-on-a-chip/
- http://www.youtube.com/watch?v=Oyqc2bFRW9I
- https://bitbucket.org/va009039/pymbed/
more info: python-on-a-chip
vm/sli.c@15:94ca5c8003e5, 2016-04-14 (annotated)
- Committer:
- va009039
- Date:
- Thu Apr 14 22:32:57 2016 +0000
- Revision:
- 15:94ca5c8003e5
- Parent:
- 0:65f1469d6bfb
update Nucleo-F401RE.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 0:65f1469d6bfb | 1 | /* |
va009039 | 0:65f1469d6bfb | 2 | # This file is Copyright 2002 Dean Hall. |
va009039 | 0:65f1469d6bfb | 3 | # This file is part of the PyMite VM. |
va009039 | 0:65f1469d6bfb | 4 | # This file is licensed under the MIT License. |
va009039 | 0:65f1469d6bfb | 5 | # See the LICENSE file for details. |
va009039 | 0:65f1469d6bfb | 6 | */ |
va009039 | 0:65f1469d6bfb | 7 | |
va009039 | 0:65f1469d6bfb | 8 | |
va009039 | 0:65f1469d6bfb | 9 | #undef __FILE_ID__ |
va009039 | 0:65f1469d6bfb | 10 | #define __FILE_ID__ 0x11 |
va009039 | 0:65f1469d6bfb | 11 | |
va009039 | 0:65f1469d6bfb | 12 | |
va009039 | 0:65f1469d6bfb | 13 | /** |
va009039 | 0:65f1469d6bfb | 14 | * \file |
va009039 | 0:65f1469d6bfb | 15 | * \brief Standard Library Interface |
va009039 | 0:65f1469d6bfb | 16 | * |
va009039 | 0:65f1469d6bfb | 17 | * PyMite requires a few functions from a few different |
va009039 | 0:65f1469d6bfb | 18 | * standard C libraries (memory, string, etc). |
va009039 | 0:65f1469d6bfb | 19 | */ |
va009039 | 0:65f1469d6bfb | 20 | |
va009039 | 0:65f1469d6bfb | 21 | |
va009039 | 0:65f1469d6bfb | 22 | #include "pm.h" |
va009039 | 0:65f1469d6bfb | 23 | |
va009039 | 0:65f1469d6bfb | 24 | |
va009039 | 0:65f1469d6bfb | 25 | /** use Duff's Device or simple for-loop for memcpy. */ |
va009039 | 0:65f1469d6bfb | 26 | #define USE_DUFFS_DEVICE 0 |
va009039 | 0:65f1469d6bfb | 27 | |
va009039 | 0:65f1469d6bfb | 28 | |
va009039 | 0:65f1469d6bfb | 29 | #if !HAVE_STRING_H |
va009039 | 0:65f1469d6bfb | 30 | |
va009039 | 0:65f1469d6bfb | 31 | void * |
va009039 | 0:65f1469d6bfb | 32 | sli_memcpy(unsigned char *to, unsigned char const *from, unsigned int n) |
va009039 | 0:65f1469d6bfb | 33 | { |
va009039 | 0:65f1469d6bfb | 34 | unsigned char *tobak; |
va009039 | 0:65f1469d6bfb | 35 | |
va009039 | 0:65f1469d6bfb | 36 | /* Store init value of to */ |
va009039 | 0:65f1469d6bfb | 37 | tobak = to; |
va009039 | 0:65f1469d6bfb | 38 | |
va009039 | 0:65f1469d6bfb | 39 | #if USE_DUFFS_DEVICE |
va009039 | 0:65f1469d6bfb | 40 | if (n > 0) |
va009039 | 0:65f1469d6bfb | 41 | { |
va009039 | 0:65f1469d6bfb | 42 | switch (n & 0x7) |
va009039 | 0:65f1469d6bfb | 43 | do |
va009039 | 0:65f1469d6bfb | 44 | { |
va009039 | 0:65f1469d6bfb | 45 | case 0: |
va009039 | 0:65f1469d6bfb | 46 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 47 | case 7: |
va009039 | 0:65f1469d6bfb | 48 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 49 | case 6: |
va009039 | 0:65f1469d6bfb | 50 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 51 | case 5: |
va009039 | 0:65f1469d6bfb | 52 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 53 | case 4: |
va009039 | 0:65f1469d6bfb | 54 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 55 | case 3: |
va009039 | 0:65f1469d6bfb | 56 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 57 | case 2: |
va009039 | 0:65f1469d6bfb | 58 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 59 | case 1: |
va009039 | 0:65f1469d6bfb | 60 | *to++ = *from++; |
va009039 | 0:65f1469d6bfb | 61 | } |
va009039 | 0:65f1469d6bfb | 62 | while ((n -= 8) > 0); |
va009039 | 0:65f1469d6bfb | 63 | } |
va009039 | 0:65f1469d6bfb | 64 | #else |
va009039 | 0:65f1469d6bfb | 65 | for (; n > 0; n--) |
va009039 | 0:65f1469d6bfb | 66 | { |
va009039 | 0:65f1469d6bfb | 67 | *to = *from; |
va009039 | 0:65f1469d6bfb | 68 | from++; |
va009039 | 0:65f1469d6bfb | 69 | to++; |
va009039 | 0:65f1469d6bfb | 70 | } |
va009039 | 0:65f1469d6bfb | 71 | #endif /* USE_DUFFS_DEVICE */ |
va009039 | 0:65f1469d6bfb | 72 | return tobak; |
va009039 | 0:65f1469d6bfb | 73 | } |
va009039 | 0:65f1469d6bfb | 74 | |
va009039 | 0:65f1469d6bfb | 75 | |
va009039 | 0:65f1469d6bfb | 76 | int |
va009039 | 0:65f1469d6bfb | 77 | sli_strlen(char const *s) |
va009039 | 0:65f1469d6bfb | 78 | { |
va009039 | 0:65f1469d6bfb | 79 | char const *si = s; |
va009039 | 0:65f1469d6bfb | 80 | int len = 0; |
va009039 | 0:65f1469d6bfb | 81 | |
va009039 | 0:65f1469d6bfb | 82 | while (*si++) |
va009039 | 0:65f1469d6bfb | 83 | { |
va009039 | 0:65f1469d6bfb | 84 | len++; |
va009039 | 0:65f1469d6bfb | 85 | } |
va009039 | 0:65f1469d6bfb | 86 | return len; |
va009039 | 0:65f1469d6bfb | 87 | } |
va009039 | 0:65f1469d6bfb | 88 | |
va009039 | 0:65f1469d6bfb | 89 | |
va009039 | 0:65f1469d6bfb | 90 | int |
va009039 | 0:65f1469d6bfb | 91 | sli_strcmp(char const *s1, char const *s2) |
va009039 | 0:65f1469d6bfb | 92 | { |
va009039 | 0:65f1469d6bfb | 93 | /* While not at either strings' end and they're same */ |
va009039 | 0:65f1469d6bfb | 94 | while ((*s1 != C_NULL) && (*s2 != C_NULL) && (*s1 == *s2)) |
va009039 | 0:65f1469d6bfb | 95 | { |
va009039 | 0:65f1469d6bfb | 96 | s1++; |
va009039 | 0:65f1469d6bfb | 97 | s2++; |
va009039 | 0:65f1469d6bfb | 98 | } |
va009039 | 0:65f1469d6bfb | 99 | |
va009039 | 0:65f1469d6bfb | 100 | /* Return string difference */ |
va009039 | 0:65f1469d6bfb | 101 | return *s1 - *s2; |
va009039 | 0:65f1469d6bfb | 102 | } |
va009039 | 0:65f1469d6bfb | 103 | |
va009039 | 0:65f1469d6bfb | 104 | |
va009039 | 0:65f1469d6bfb | 105 | int |
va009039 | 0:65f1469d6bfb | 106 | sli_strncmp(char const *s1, char const *s2, unsigned int n) |
va009039 | 0:65f1469d6bfb | 107 | { |
va009039 | 0:65f1469d6bfb | 108 | unsigned int i = 0; |
va009039 | 0:65f1469d6bfb | 109 | |
va009039 | 0:65f1469d6bfb | 110 | if (n == 0) |
va009039 | 0:65f1469d6bfb | 111 | { |
va009039 | 0:65f1469d6bfb | 112 | return 0; |
va009039 | 0:65f1469d6bfb | 113 | } |
va009039 | 0:65f1469d6bfb | 114 | |
va009039 | 0:65f1469d6bfb | 115 | /* Scan n bytes in string */ |
va009039 | 0:65f1469d6bfb | 116 | for (i = 0; i < n; i++) |
va009039 | 0:65f1469d6bfb | 117 | { |
va009039 | 0:65f1469d6bfb | 118 | /* If bytes differ, return difference */ |
va009039 | 0:65f1469d6bfb | 119 | if (s1[i] != s2[i]) |
va009039 | 0:65f1469d6bfb | 120 | { |
va009039 | 0:65f1469d6bfb | 121 | return s1[i] - s2[i]; |
va009039 | 0:65f1469d6bfb | 122 | } |
va009039 | 0:65f1469d6bfb | 123 | } |
va009039 | 0:65f1469d6bfb | 124 | return 0; |
va009039 | 0:65f1469d6bfb | 125 | } |
va009039 | 0:65f1469d6bfb | 126 | |
va009039 | 0:65f1469d6bfb | 127 | #endif /* HAVE_STRING_H */ |
va009039 | 0:65f1469d6bfb | 128 | |
va009039 | 0:65f1469d6bfb | 129 | |
va009039 | 0:65f1469d6bfb | 130 | /* |
va009039 | 0:65f1469d6bfb | 131 | * This function is moved outside of HAVE_STRING_H because the one in string.h |
va009039 | 0:65f1469d6bfb | 132 | * will not accept a null value for the second arg |
va009039 | 0:65f1469d6bfb | 133 | */ |
va009039 | 0:65f1469d6bfb | 134 | void |
va009039 | 0:65f1469d6bfb | 135 | sli_memset(unsigned char *dest, char const val, unsigned int n) |
va009039 | 0:65f1469d6bfb | 136 | { |
va009039 | 0:65f1469d6bfb | 137 | unsigned int i; |
va009039 | 0:65f1469d6bfb | 138 | |
va009039 | 0:65f1469d6bfb | 139 | for (i = 0; i < n; i++) |
va009039 | 0:65f1469d6bfb | 140 | { |
va009039 | 0:65f1469d6bfb | 141 | *dest = (unsigned char)val; |
va009039 | 0:65f1469d6bfb | 142 | dest++; |
va009039 | 0:65f1469d6bfb | 143 | } |
va009039 | 0:65f1469d6bfb | 144 | } |
va009039 | 0:65f1469d6bfb | 145 | |
va009039 | 0:65f1469d6bfb | 146 | void |
va009039 | 0:65f1469d6bfb | 147 | sli_puts(uint8_t * s) |
va009039 | 0:65f1469d6bfb | 148 | { |
va009039 | 0:65f1469d6bfb | 149 | uint8_t *ps = s; |
va009039 | 0:65f1469d6bfb | 150 | uint8_t c; |
va009039 | 0:65f1469d6bfb | 151 | |
va009039 | 0:65f1469d6bfb | 152 | c = *ps; |
va009039 | 0:65f1469d6bfb | 153 | ps++; |
va009039 | 0:65f1469d6bfb | 154 | while (c != '\0') |
va009039 | 0:65f1469d6bfb | 155 | { |
va009039 | 0:65f1469d6bfb | 156 | plat_putByte(c); |
va009039 | 0:65f1469d6bfb | 157 | c = *ps; |
va009039 | 0:65f1469d6bfb | 158 | ps++; |
va009039 | 0:65f1469d6bfb | 159 | } |
va009039 | 0:65f1469d6bfb | 160 | } |
va009039 | 0:65f1469d6bfb | 161 | |
va009039 | 0:65f1469d6bfb | 162 | |
va009039 | 0:65f1469d6bfb | 163 | PmReturn_t |
va009039 | 0:65f1469d6bfb | 164 | sli_ltoa10(int32_t value, uint8_t *buf, uint8_t buflen) |
va009039 | 0:65f1469d6bfb | 165 | { |
va009039 | 0:65f1469d6bfb | 166 | int32_t const decimal_places[] = { 1000000000, 100000000, 10000000, 1000000, |
va009039 | 0:65f1469d6bfb | 167 | 100000, 10000, 1000, 100, 10, 1 }; |
va009039 | 0:65f1469d6bfb | 168 | int32_t decimal_place; |
va009039 | 0:65f1469d6bfb | 169 | int32_t number; |
va009039 | 0:65f1469d6bfb | 170 | uint8_t c; |
va009039 | 0:65f1469d6bfb | 171 | uint8_t printed_one = C_FALSE; |
va009039 | 0:65f1469d6bfb | 172 | uint8_t i; |
va009039 | 0:65f1469d6bfb | 173 | uint8_t j; |
va009039 | 0:65f1469d6bfb | 174 | PmReturn_t retval = PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 175 | |
va009039 | 0:65f1469d6bfb | 176 | C_ASSERT(buflen >= 12); |
va009039 | 0:65f1469d6bfb | 177 | |
va009039 | 0:65f1469d6bfb | 178 | number = value; |
va009039 | 0:65f1469d6bfb | 179 | if (number == 0) |
va009039 | 0:65f1469d6bfb | 180 | { |
va009039 | 0:65f1469d6bfb | 181 | buf[0] = '0'; |
va009039 | 0:65f1469d6bfb | 182 | buf[1] = '\0'; |
va009039 | 0:65f1469d6bfb | 183 | return retval; |
va009039 | 0:65f1469d6bfb | 184 | } |
va009039 | 0:65f1469d6bfb | 185 | |
va009039 | 0:65f1469d6bfb | 186 | /* Special case (can't convert it to positive value) */ |
va009039 | 0:65f1469d6bfb | 187 | if (number == -2147483648) |
va009039 | 0:65f1469d6bfb | 188 | { |
va009039 | 0:65f1469d6bfb | 189 | sli_memcpy(buf, (unsigned char *)"-2147483648", 11); |
va009039 | 0:65f1469d6bfb | 190 | return PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 191 | } |
va009039 | 0:65f1469d6bfb | 192 | |
va009039 | 0:65f1469d6bfb | 193 | j = 0; |
va009039 | 0:65f1469d6bfb | 194 | if (number < 0) |
va009039 | 0:65f1469d6bfb | 195 | { |
va009039 | 0:65f1469d6bfb | 196 | buf[0] = '-'; |
va009039 | 0:65f1469d6bfb | 197 | j++; |
va009039 | 0:65f1469d6bfb | 198 | number = -number; |
va009039 | 0:65f1469d6bfb | 199 | } |
va009039 | 0:65f1469d6bfb | 200 | |
va009039 | 0:65f1469d6bfb | 201 | for (i = 0; i < 10; i++) |
va009039 | 0:65f1469d6bfb | 202 | { |
va009039 | 0:65f1469d6bfb | 203 | decimal_place = decimal_places[i]; |
va009039 | 0:65f1469d6bfb | 204 | c = '0'; |
va009039 | 0:65f1469d6bfb | 205 | while (number >= decimal_place) |
va009039 | 0:65f1469d6bfb | 206 | { |
va009039 | 0:65f1469d6bfb | 207 | number -= decimal_place; |
va009039 | 0:65f1469d6bfb | 208 | c++; |
va009039 | 0:65f1469d6bfb | 209 | } |
va009039 | 0:65f1469d6bfb | 210 | if ((c != '0') || printed_one) |
va009039 | 0:65f1469d6bfb | 211 | { |
va009039 | 0:65f1469d6bfb | 212 | buf[j++] = c; |
va009039 | 0:65f1469d6bfb | 213 | printed_one = C_TRUE; |
va009039 | 0:65f1469d6bfb | 214 | } |
va009039 | 0:65f1469d6bfb | 215 | } |
va009039 | 0:65f1469d6bfb | 216 | buf[j] = '\0'; |
va009039 | 0:65f1469d6bfb | 217 | |
va009039 | 0:65f1469d6bfb | 218 | return retval; |
va009039 | 0:65f1469d6bfb | 219 | } |
va009039 | 0:65f1469d6bfb | 220 | |
va009039 | 0:65f1469d6bfb | 221 | char const * const hexChars = "0123456789abcdef"; |
va009039 | 0:65f1469d6bfb | 222 | |
va009039 | 0:65f1469d6bfb | 223 | /* MUST show leading zeros because callers don't keep track */ |
va009039 | 0:65f1469d6bfb | 224 | PmReturn_t |
va009039 | 0:65f1469d6bfb | 225 | sli_btoa16(uint8_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase) |
va009039 | 0:65f1469d6bfb | 226 | { |
va009039 | 0:65f1469d6bfb | 227 | C_ASSERT(buflen >= 3); |
va009039 | 0:65f1469d6bfb | 228 | |
va009039 | 0:65f1469d6bfb | 229 | if (upperCase) upperCase = 'A' - 'a'; |
va009039 | 0:65f1469d6bfb | 230 | |
va009039 | 0:65f1469d6bfb | 231 | buf[0] = (value >> 4) > 9 |
va009039 | 0:65f1469d6bfb | 232 | ? hexChars[value >> 4] + upperCase |
va009039 | 0:65f1469d6bfb | 233 | : hexChars[value >> 4]; |
va009039 | 0:65f1469d6bfb | 234 | buf[1] = (value & 0x0F) > 9 |
va009039 | 0:65f1469d6bfb | 235 | ? hexChars[value & 0x0F] + upperCase |
va009039 | 0:65f1469d6bfb | 236 | : hexChars[value & 0x0F]; |
va009039 | 0:65f1469d6bfb | 237 | buf[2] = '\0'; |
va009039 | 0:65f1469d6bfb | 238 | |
va009039 | 0:65f1469d6bfb | 239 | return PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 240 | } |
va009039 | 0:65f1469d6bfb | 241 | |
va009039 | 0:65f1469d6bfb | 242 | |
va009039 | 0:65f1469d6bfb | 243 | /* Does NOT show leading zeroes */ |
va009039 | 0:65f1469d6bfb | 244 | PmReturn_t |
va009039 | 0:65f1469d6bfb | 245 | sli_ltoa16(int32_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase) |
va009039 | 0:65f1469d6bfb | 246 | { |
va009039 | 0:65f1469d6bfb | 247 | int8_t i; |
va009039 | 0:65f1469d6bfb | 248 | uint8_t j = 0; |
va009039 | 0:65f1469d6bfb | 249 | uint8_t showZero = C_FALSE; |
va009039 | 0:65f1469d6bfb | 250 | uint8_t nibble; |
va009039 | 0:65f1469d6bfb | 251 | |
va009039 | 0:65f1469d6bfb | 252 | C_ASSERT(buflen >= 9); |
va009039 | 0:65f1469d6bfb | 253 | |
va009039 | 0:65f1469d6bfb | 254 | if (upperCase) upperCase = 'A' - 'a'; |
va009039 | 0:65f1469d6bfb | 255 | |
va009039 | 0:65f1469d6bfb | 256 | for (i = 28; i >= 0; i -= 4) |
va009039 | 0:65f1469d6bfb | 257 | { |
va009039 | 0:65f1469d6bfb | 258 | nibble = ((value >> i) & 0xF); |
va009039 | 0:65f1469d6bfb | 259 | if ((nibble == 0) && !showZero) continue; |
va009039 | 0:65f1469d6bfb | 260 | buf[j++] = (nibble > 9) |
va009039 | 0:65f1469d6bfb | 261 | ? hexChars[nibble] + upperCase |
va009039 | 0:65f1469d6bfb | 262 | : hexChars[nibble]; |
va009039 | 0:65f1469d6bfb | 263 | showZero = C_TRUE; |
va009039 | 0:65f1469d6bfb | 264 | } |
va009039 | 0:65f1469d6bfb | 265 | buf[j] = '\0'; |
va009039 | 0:65f1469d6bfb | 266 | |
va009039 | 0:65f1469d6bfb | 267 | return PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 268 | } |
va009039 | 0:65f1469d6bfb | 269 | |
va009039 | 0:65f1469d6bfb | 270 | |
va009039 | 0:65f1469d6bfb | 271 | PmReturn_t |
va009039 | 0:65f1469d6bfb | 272 | sli_ptoa16(intptr_t value, uint8_t *buf, uint8_t buflen, uint8_t upperCase) |
va009039 | 0:65f1469d6bfb | 273 | { |
va009039 | 0:65f1469d6bfb | 274 | PmReturn_t retval; |
va009039 | 0:65f1469d6bfb | 275 | int8_t i; |
va009039 | 0:65f1469d6bfb | 276 | int8_t j; |
va009039 | 0:65f1469d6bfb | 277 | |
va009039 | 0:65f1469d6bfb | 278 | C_ASSERT(buflen >= 2 * sizeof(intptr_t) + 1); |
va009039 | 0:65f1469d6bfb | 279 | |
va009039 | 0:65f1469d6bfb | 280 | /* Print the hex value, most significant byte first */ |
va009039 | 0:65f1469d6bfb | 281 | for (j = 0, i = 8 * sizeof(intptr_t) - 8; i >= 0; i -= 8, j += 2) |
va009039 | 0:65f1469d6bfb | 282 | { |
va009039 | 0:65f1469d6bfb | 283 | retval = sli_btoa16((value >> i) & 0xFF, &buf[j], buflen - j, upperCase); |
va009039 | 0:65f1469d6bfb | 284 | PM_BREAK_IF_ERROR(retval); |
va009039 | 0:65f1469d6bfb | 285 | } |
va009039 | 0:65f1469d6bfb | 286 | |
va009039 | 0:65f1469d6bfb | 287 | return retval; |
va009039 | 0:65f1469d6bfb | 288 | } |
va009039 | 0:65f1469d6bfb | 289 | |
va009039 | 0:65f1469d6bfb | 290 | |
va009039 | 0:65f1469d6bfb | 291 | typedef union { |
va009039 | 0:65f1469d6bfb | 292 | int32_t L; |
va009039 | 0:65f1469d6bfb | 293 | float F; |
va009039 | 0:65f1469d6bfb | 294 | } LF_t; |
va009039 | 0:65f1469d6bfb | 295 | |
va009039 | 0:65f1469d6bfb | 296 | |
va009039 | 0:65f1469d6bfb | 297 | /* The buf MUST be at least 15 bytes long */ |
va009039 | 0:65f1469d6bfb | 298 | PmReturn_t |
va009039 | 0:65f1469d6bfb | 299 | sli_ftoa(float f, uint8_t *buf, uint8_t buflen) |
va009039 | 0:65f1469d6bfb | 300 | { |
va009039 | 0:65f1469d6bfb | 301 | uint32_t mantissa, int_part, frac_part; |
va009039 | 0:65f1469d6bfb | 302 | int16_t exp2; |
va009039 | 0:65f1469d6bfb | 303 | LF_t x; |
va009039 | 0:65f1469d6bfb | 304 | uint8_t *p; |
va009039 | 0:65f1469d6bfb | 305 | int8_t adj = 0; |
va009039 | 0:65f1469d6bfb | 306 | PmReturn_t retval = PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 307 | |
va009039 | 0:65f1469d6bfb | 308 | C_ASSERT(buflen >= 15); |
va009039 | 0:65f1469d6bfb | 309 | |
va009039 | 0:65f1469d6bfb | 310 | if (f == 0.0) |
va009039 | 0:65f1469d6bfb | 311 | { |
va009039 | 0:65f1469d6bfb | 312 | buf[0] = '0'; |
va009039 | 0:65f1469d6bfb | 313 | buf[1] = '.'; |
va009039 | 0:65f1469d6bfb | 314 | buf[2] = '0'; |
va009039 | 0:65f1469d6bfb | 315 | buf[3] = '\0'; |
va009039 | 0:65f1469d6bfb | 316 | return PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 317 | } |
va009039 | 0:65f1469d6bfb | 318 | x.F = f; |
va009039 | 0:65f1469d6bfb | 319 | |
va009039 | 0:65f1469d6bfb | 320 | exp2 = (0xFF & (x.L >> 23)) - 127; |
va009039 | 0:65f1469d6bfb | 321 | mantissa = (x.L & 0xFFFFFF) | 0x800000; |
va009039 | 0:65f1469d6bfb | 322 | frac_part = 0; |
va009039 | 0:65f1469d6bfb | 323 | int_part = 0; |
va009039 | 0:65f1469d6bfb | 324 | p = buf; |
va009039 | 0:65f1469d6bfb | 325 | |
va009039 | 0:65f1469d6bfb | 326 | /* Adjust large exponents using the approximation: 2**10 == k*10**3 */ |
va009039 | 0:65f1469d6bfb | 327 | while (exp2 >= 31) |
va009039 | 0:65f1469d6bfb | 328 | { |
va009039 | 0:65f1469d6bfb | 329 | /* Reduce the binary exponent here (incr the decimal exponent below) */ |
va009039 | 0:65f1469d6bfb | 330 | exp2 -= 10; |
va009039 | 0:65f1469d6bfb | 331 | adj++; |
va009039 | 0:65f1469d6bfb | 332 | |
va009039 | 0:65f1469d6bfb | 333 | /* |
va009039 | 0:65f1469d6bfb | 334 | * To use the approximation above, the mantissa must be multiplied by k |
va009039 | 0:65f1469d6bfb | 335 | * where k = 1.024 ~= (1 + 12583/(2**19)) |
va009039 | 0:65f1469d6bfb | 336 | * Divide first to avoid integer overflow (the mantissa is 24 bits) |
va009039 | 0:65f1469d6bfb | 337 | */ |
va009039 | 0:65f1469d6bfb | 338 | mantissa += ((mantissa >> 6) * 12583) >> 13; |
va009039 | 0:65f1469d6bfb | 339 | } |
va009039 | 0:65f1469d6bfb | 340 | |
va009039 | 0:65f1469d6bfb | 341 | if (exp2 < -23) |
va009039 | 0:65f1469d6bfb | 342 | { |
va009039 | 0:65f1469d6bfb | 343 | // Unable to handle large negative exponents at this time |
va009039 | 0:65f1469d6bfb | 344 | *p++ = '?'; |
va009039 | 0:65f1469d6bfb | 345 | return PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 346 | } |
va009039 | 0:65f1469d6bfb | 347 | else if (exp2 >= 23) |
va009039 | 0:65f1469d6bfb | 348 | { |
va009039 | 0:65f1469d6bfb | 349 | int_part = mantissa << (exp2 - 23); |
va009039 | 0:65f1469d6bfb | 350 | } |
va009039 | 0:65f1469d6bfb | 351 | else if (exp2 >= 0) |
va009039 | 0:65f1469d6bfb | 352 | { |
va009039 | 0:65f1469d6bfb | 353 | int_part = mantissa >> (23 - exp2); |
va009039 | 0:65f1469d6bfb | 354 | frac_part = (mantissa << (exp2 + 1)) & 0xFFFFFF; |
va009039 | 0:65f1469d6bfb | 355 | } |
va009039 | 0:65f1469d6bfb | 356 | else /* if (exp2 < 0) */ |
va009039 | 0:65f1469d6bfb | 357 | { |
va009039 | 0:65f1469d6bfb | 358 | frac_part = (mantissa & 0xFFFFFF) >> -(exp2 + 1); |
va009039 | 0:65f1469d6bfb | 359 | } |
va009039 | 0:65f1469d6bfb | 360 | |
va009039 | 0:65f1469d6bfb | 361 | if (x.L < 0) |
va009039 | 0:65f1469d6bfb | 362 | { |
va009039 | 0:65f1469d6bfb | 363 | *p++ = '-'; |
va009039 | 0:65f1469d6bfb | 364 | } |
va009039 | 0:65f1469d6bfb | 365 | |
va009039 | 0:65f1469d6bfb | 366 | if (int_part == 0) |
va009039 | 0:65f1469d6bfb | 367 | { |
va009039 | 0:65f1469d6bfb | 368 | *p++ = '0'; |
va009039 | 0:65f1469d6bfb | 369 | } |
va009039 | 0:65f1469d6bfb | 370 | else |
va009039 | 0:65f1469d6bfb | 371 | { |
va009039 | 0:65f1469d6bfb | 372 | retval = sli_ltoa10(int_part, p, buflen - (p - buf)); |
va009039 | 0:65f1469d6bfb | 373 | PM_RETURN_IF_ERROR(retval); |
va009039 | 0:65f1469d6bfb | 374 | while (*p) p++; |
va009039 | 0:65f1469d6bfb | 375 | } |
va009039 | 0:65f1469d6bfb | 376 | *p++ = '.'; |
va009039 | 0:65f1469d6bfb | 377 | |
va009039 | 0:65f1469d6bfb | 378 | if (frac_part == 0) |
va009039 | 0:65f1469d6bfb | 379 | { |
va009039 | 0:65f1469d6bfb | 380 | *p++ = '0'; |
va009039 | 0:65f1469d6bfb | 381 | } |
va009039 | 0:65f1469d6bfb | 382 | else |
va009039 | 0:65f1469d6bfb | 383 | { |
va009039 | 0:65f1469d6bfb | 384 | char m, max; |
va009039 | 0:65f1469d6bfb | 385 | |
va009039 | 0:65f1469d6bfb | 386 | max = buflen - (p - buf) - 1; |
va009039 | 0:65f1469d6bfb | 387 | if (max > 6) |
va009039 | 0:65f1469d6bfb | 388 | { |
va009039 | 0:65f1469d6bfb | 389 | max = 6; |
va009039 | 0:65f1469d6bfb | 390 | } |
va009039 | 0:65f1469d6bfb | 391 | |
va009039 | 0:65f1469d6bfb | 392 | /* Print fractional part */ |
va009039 | 0:65f1469d6bfb | 393 | for (m = 0; m < max; m++) |
va009039 | 0:65f1469d6bfb | 394 | { |
va009039 | 0:65f1469d6bfb | 395 | frac_part *= 10; |
va009039 | 0:65f1469d6bfb | 396 | *p++ = '0' + (frac_part >> 24); |
va009039 | 0:65f1469d6bfb | 397 | frac_part &= 0xFFFFFF; |
va009039 | 0:65f1469d6bfb | 398 | } |
va009039 | 0:65f1469d6bfb | 399 | |
va009039 | 0:65f1469d6bfb | 400 | /* Remove ending zeroes */ |
va009039 | 0:65f1469d6bfb | 401 | //for (--p; p[0] == '0' && p[-1] != '.'; --p); |
va009039 | 0:65f1469d6bfb | 402 | //++p; |
va009039 | 0:65f1469d6bfb | 403 | } |
va009039 | 0:65f1469d6bfb | 404 | |
va009039 | 0:65f1469d6bfb | 405 | /* |
va009039 | 0:65f1469d6bfb | 406 | * If the exponent is large (adjustment took place above), |
va009039 | 0:65f1469d6bfb | 407 | * normalize the string to scientific notation |
va009039 | 0:65f1469d6bfb | 408 | */ |
va009039 | 0:65f1469d6bfb | 409 | if (adj != 0) |
va009039 | 0:65f1469d6bfb | 410 | { |
va009039 | 0:65f1469d6bfb | 411 | uint8_t i; |
va009039 | 0:65f1469d6bfb | 412 | |
va009039 | 0:65f1469d6bfb | 413 | /* Shift chars to make room for the new decimal point */ |
va009039 | 0:65f1469d6bfb | 414 | i = (p - buf + 1); |
va009039 | 0:65f1469d6bfb | 415 | i = (i > (buflen - 1)) ? buflen - 1 : i; |
va009039 | 0:65f1469d6bfb | 416 | for (; i > 1; i--) |
va009039 | 0:65f1469d6bfb | 417 | { |
va009039 | 0:65f1469d6bfb | 418 | buf[i] = buf[i-1]; |
va009039 | 0:65f1469d6bfb | 419 | } |
va009039 | 0:65f1469d6bfb | 420 | |
va009039 | 0:65f1469d6bfb | 421 | /* Find the index of the old decimal point */ |
va009039 | 0:65f1469d6bfb | 422 | for (i = 6; (buf[i] != '.') && (i < 15); i++); |
va009039 | 0:65f1469d6bfb | 423 | |
va009039 | 0:65f1469d6bfb | 424 | /* Set the new decimal point (normalized) */ |
va009039 | 0:65f1469d6bfb | 425 | buf[1] = '.'; |
va009039 | 0:65f1469d6bfb | 426 | |
va009039 | 0:65f1469d6bfb | 427 | /* |
va009039 | 0:65f1469d6bfb | 428 | * Adjust the decimal exponent (3 decimal places for every 10 bits) |
va009039 | 0:65f1469d6bfb | 429 | * and add the amount for the normalization |
va009039 | 0:65f1469d6bfb | 430 | */ |
va009039 | 0:65f1469d6bfb | 431 | p = &buf[8]; |
va009039 | 0:65f1469d6bfb | 432 | *p++ = 'e'; |
va009039 | 0:65f1469d6bfb | 433 | *p++ = '+'; |
va009039 | 0:65f1469d6bfb | 434 | retval = sli_ltoa10(3 * adj + (i - 2), p, buflen - (p - buf)); |
va009039 | 0:65f1469d6bfb | 435 | PM_RETURN_IF_ERROR(retval); |
va009039 | 0:65f1469d6bfb | 436 | while (*p) p++; |
va009039 | 0:65f1469d6bfb | 437 | } |
va009039 | 0:65f1469d6bfb | 438 | |
va009039 | 0:65f1469d6bfb | 439 | *p = '\0'; |
va009039 | 0:65f1469d6bfb | 440 | |
va009039 | 0:65f1469d6bfb | 441 | return PM_RET_OK; |
va009039 | 0:65f1469d6bfb | 442 | } |