@@ -210,34 +210,94 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
210210 // prevent crash if called with base == 1
211211 if (base < 2 ) base = 10 ;
212212
213- unsigned long reverse = 0 ;
214- uint8_t digits = 0 ;
215- char avoid_overflow = n % base;
216- 217- // this step and 'avoid_overflow' will make sure it stays in unsigned long range beeing able to print all 10 digits no matter what
218- n /= base;
219- 220- // reverse the number and count digits
221- while (n != 0 ) {
222- uint8_t remainder = n % base;
223- reverse = reverse * base + remainder;
224- n /= base;
225- digits++;
226- }
227- 228- // from here onwards reuse of variable 'n' to count written chars
229- while (digits--) {
230- char c = reverse % base;
231- reverse /= base;
232- 233- c = (c < 10 ? c + ' 0' : c + ' A' - 10 );
234- n += write (c);
213+ // use -D ARDUINO_PRINT_NUMBER_GENERIC_ONLY when compiling to get only the generic version
214+ #ifndef ARDUINO_PRINT_NUMBER_GENERIC_ONLY
215+ switch (base) {
216+ case 16 :
217+ // optimized version for hex prints
218+ {
219+ uint8_t *access = (uint8_t *) &n;
220+ uint8_t written = 0 ;
221+ for (int8_t i=3 ; i>=0 ; i--) {
222+ char c;
223+ c = (access[i] & 0xf0 ) >> 4 ;
224+ if (c != 0 || written != 0 ) {
225+ c = (c < 10 ? c + ' 0' : c + ' A' - 10 );
226+ written += write (c);
227+ } // else: skip leading zeros
228+ c = access[i] & 0x0f ;
229+ if (c != 0 || written != 0 ) {
230+ // skip leading zeros
231+ c = (c < 10 ? c + ' 0' : c + ' A' - 10 );
232+ written += write (c);
233+ } // else: skip leading zeros
234+ }
235+ return written;
236+ }
237+ case 2 :
238+ // optimized version for binary prints
239+ {
240+ uint8_t *access = (uint8_t *) &n;
241+ uint8_t written = 0 ;
242+ for (int8_t i=3 ; i>=0 ; i--) {
243+ if (access[i] == 0 && written == 0 ) {
244+ // skip leading zeros
245+ continue ;
246+ }
247+ for (int8_t j=7 ; j>=0 ; j--) {
248+ char c;
249+ if (j == 0 ) {
250+ // avoid shift by 0 - undefined
251+ c = (access[i] & 0x01 );
252+ } else {
253+ c = (access[i] & 1 <<j) >> j;
254+ }
255+ if (c == 0 && written == 0 ) {
256+ // skip leading zeros
257+ continue ;
258+ }
259+ c = (c < 10 ? c + ' 0' : c + ' A' - 10 );
260+ written += write (c);
261+ }
262+ }
263+ return written;
264+ }
265+ default :
266+ // the generic implementation
267+ #endif
268+ {
269+ unsigned long reverse = 0 ;
270+ uint8_t digits = 0 ;
271+ char avoid_overflow = n % base;
272+ 273+ // this step and 'avoid_overflow' will make sure it stays in unsigned long range beeing able to print all 10 digits no matter what
274+ n /= base;
275+ 276+ // reverse the number and count digits
277+ while (n != 0 ) {
278+ uint8_t remainder = n % base;
279+ reverse = reverse * base + remainder;
280+ n /= base;
281+ digits++;
282+ }
283+ 284+ // from here onwards reuse of variable 'n' to count written chars
285+ while (digits--) {
286+ char c = reverse % base;
287+ reverse /= base;
288+ 289+ c = (c < 10 ? c + ' 0' : c + ' A' - 10 );
290+ n += write (c);
291+ }
292+ 293+ avoid_overflow = (avoid_overflow < 10 ? avoid_overflow + ' 0' : avoid_overflow + ' A' - 10 );
294+ n += write (avoid_overflow);
295+ 296+ return n;
297+ }
298+ #ifndef ARDUINO_PRINT_NUMBER_GENERIC_ONLY
235299 }
236- 237- avoid_overflow = (avoid_overflow < 10 ? avoid_overflow + ' 0' : avoid_overflow + ' A' - 10 );
238- n += write (avoid_overflow);
239- 240- return n;
300+ #endif
241301}
242302
243303size_t Print::printFloat (double number, uint8_t digits)
0 commit comments