Math-timising

Part of a project I’m working on requires converting from a time string (hhmmss) to a single integer of seconds. My first approach was to multiply each character individually.

void gps_import(void) {
	unsigned char c;

	c = gps[0] - 48;
	utc = c * 36000;
	c = gps[1] - 48;
	utc += c * 3600;
	c = gps[2] - 48;
	utc += c * 600;
	c = gps[3] - 48;
	utc += c * 60;

	gps_updated = false;
}

Here is the disassembly of the multiplication for the hour’s tens column:

	utc = c * 36000;
 206:	50 e0       	ldi	r21, 0x00	; 0
 208:	60 e0       	ldi	r22, 0x00	; 0
 20a:	70 e0       	ldi	r23, 0x00	; 0
 20c:	8a 01       	movw	r16, r20
 20e:	9b 01       	movw	r18, r22
 210:	00 0f       	add	r16, r16
 212:	11 1f       	adc	r17, r17
 214:	22 1f       	adc	r18, r18
 216:	33 1f       	adc	r19, r19
 218:	00 0f       	add	r16, r16
 21a:	11 1f       	adc	r17, r17
 21c:	22 1f       	adc	r18, r18
 21e:	33 1f       	adc	r19, r19
 220:	d9 01       	movw	r26, r18
 222:	c8 01       	movw	r24, r16
 224:	88 0f       	add	r24, r24
 226:	99 1f       	adc	r25, r25
 228:	aa 1f       	adc	r26, r26
 22a:	bb 1f       	adc	r27, r27
 22c:	88 0f       	add	r24, r24
 22e:	99 1f       	adc	r25, r25
 230:	aa 1f       	adc	r26, r26
 232:	bb 1f       	adc	r27, r27
 234:	80 0f       	add	r24, r16
 236:	91 1f       	adc	r25, r17
 238:	a2 1f       	adc	r26, r18
 23a:	b3 1f       	adc	r27, r19
 23c:	84 1b       	sub	r24, r20
 23e:	95 0b       	sbc	r25, r21
 240:	a6 0b       	sbc	r26, r22
 242:	b7 0b       	sbc	r27, r23
 244:	88 0f       	add	r24, r24
 246:	99 1f       	adc	r25, r25
 248:	aa 1f       	adc	r26, r26
 24a:	bb 1f       	adc	r27, r27
 24c:	88 0f       	add	r24, r24
 24e:	99 1f       	adc	r25, r25
 250:	aa 1f       	adc	r26, r26
 252:	bb 1f       	adc	r27, r27
 254:	84 1b       	sub	r24, r20
 256:	95 0b       	sbc	r25, r21
 258:	a6 0b       	sbc	r26, r22
 25a:	b7 0b       	sbc	r27, r23
 25c:	88 0f       	add	r24, r24
 25e:	99 1f       	adc	r25, r25
 260:	aa 1f       	adc	r26, r26
 262:	bb 1f       	adc	r27, r27
 264:	88 0f       	add	r24, r24
 266:	99 1f       	adc	r25, r25
 268:	aa 1f       	adc	r26, r26
 26a:	bb 1f       	adc	r27, r27
 26c:	88 0f       	add	r24, r24
 26e:	99 1f       	adc	r25, r25
 270:	aa 1f       	adc	r26, r26
 272:	bb 1f       	adc	r27, r27
 274:	88 0f       	add	r24, r24
 276:	99 1f       	adc	r25, r25
 278:	aa 1f       	adc	r26, r26
 27a:	bb 1f       	adc	r27, r27
 27c:	88 0f       	add	r24, r24
 27e:	99 1f       	adc	r25, r25
 280:	aa 1f       	adc	r26, r26
 282:	bb 1f       	adc	r27, r27
 284:	ac 01       	movw	r20, r24
 286:	bd 01       	movw	r22, r26
 288:	44 0f       	add	r20, r20
 28a:	55 1f       	adc	r21, r21
 28c:	66 1f       	adc	r22, r22
 28e:	77 1f       	adc	r23, r23
 290:	44 0f       	add	r20, r20
 292:	55 1f       	adc	r21, r21
 294:	66 1f       	adc	r22, r22
 296:	77 1f       	adc	r23, r23
 298:	44 0f       	add	r20, r20
 29a:	55 1f       	adc	r21, r21
 29c:	66 1f       	adc	r22, r22
 29e:	77 1f       	adc	r23, r23
 2a0:	44 0f       	add	r20, r20
 2a2:	55 1f       	adc	r21, r21
 2a4:	66 1f       	adc	r22, r22
 2a6:	77 1f       	adc	r23, r23
 2a8:	8a 01       	movw	r16, r20
 2aa:	9b 01       	movw	r18, r22
 2ac:	08 1b       	sub	r16, r24
 2ae:	19 0b       	sbc	r17, r25
 2b0:	2a 0b       	sbc	r18, r26
 2b2:	3b 0b       	sbc	r19, r27
 2b4:	d9 01       	movw	r26, r18
 2b6:	c8 01       	movw	r24, r16

As you can see, it takes quite a few eight bit processor instructions to multiply by 36000. My solution was to change the conversion math and integrate each place successively.

void gps_import(void) {
	unsigned char c;

	c = gps[0] - 48;
	utc = c;
	utc *= 10;
	c = gps[1] - 48;
	utc += c;
	utc *= 6;
	c = gps[2] - 48;
	utc += c;
	utc *= 10;
	c = gps[3] - 48;
	utc += c;
	utc *= 60;

	gps_updated = false;
}

Here is the disassembly for the same hour tens column multiplication. The rest is integrated into the multiplication for the other columns.

	utc *= 10;
 208:	88 0f       	add	r24, r24
 20a:	99 1f       	adc	r25, r25
 20c:	aa 1f       	adc	r26, r26
 20e:	bb 1f       	adc	r27, r27
 210:	ac 01       	movw	r20, r24
 212:	bd 01       	movw	r22, r26
 214:	44 0f       	add	r20, r20
 216:	55 1f       	adc	r21, r21
 218:	66 1f       	adc	r22, r22
 21a:	77 1f       	adc	r23, r23
 21c:	44 0f       	add	r20, r20
 21e:	55 1f       	adc	r21, r21
 220:	66 1f       	adc	r22, r22
 222:	77 1f       	adc	r23, r23
 224:	84 0f       	add	r24, r20
 226:	95 1f       	adc	r25, r21
 228:	a6 1f       	adc	r26, r22
 22a:	b7 1f       	adc	r27, r23

I’m quite pleased with myself really, haha.

Leave a Reply

Your email address will not be published. Required fields are marked *