/*
 * assign22.S
 *
 *  Created on: Sep 7, 2011
 *      Author: patb
 *
 * credit card checker
 */


	.syntax unified
#include "stm32f10x_asm.h"
	.global _start

	.text
	.word 0x20002000
	.word _start+1


_start:
main:

	// power up the zones of the chip
	ldr r0, =0x40021018			//RCC
	ldr	r1, =0x00044a3d
	str r1,[r0]

	// turn on the normally not-connected pins
	ldr r0,=0x02008000
	ldr r1,=0x40010004
	str r0,[r1]

	// set the data direction registers
	ldr r1,=0x40011000		// DDRC_HI
	mov r0,#0x11111111
	str r0,[r1]
	ldr r1,=0x40011004		// DDRC_HI
	str r0,[r1]

	ldr r4,=0x4001100C		// PCOUT

	// now test the credit cards
	ldr r0,=card1
	bl  checkCC

	cmp r0,#1			// check the return value
	bne red_on
	mov r1,#0x0200		// the green light pattern
	strh r1,[r4]		// into PCOUT
	b next_card
red_on:
	mov r1,#0x0400		// the red light pattern
	strh r1,[r4]

next_card:
	ldr r0,=card2
	bl  checkCC

	cmp r0,#1
	bne red_on2
	mov r1,#0x0200
	strh r1,[r4]
	b next_card
red_on2:
	mov r1,#0x0400
	strh r1,[r4]

	b main


/* int checkCC(char* pCCNumber)
 * argument in r0, a pointer to an ASCIIZ string
 * returns r0==1 if this is a good credit card, 0 otherwise
 * destroys r0...r3
 *
 * checkCC(char* pCCNumber) {
 *   int sum = 0;		// using r1
 *   char c;			// using r2
 *   int pos;			// using r3
 *   // run through all the elements of pCCNumber, till we hit a binary 0
 *   for (pos=0; *(pCCNumber+pos) != 0; pos++) {
 *      c = *(pCCNumber+pos);
 *      c = asciiToHex(c);
 *      if (pos is 0,2,4,6,...) {
 *         c = 2*c;
 *         if (c>=10)
 *            c = c+1;
 *      }
 *      sum = sum + c;
 *   }
 *   // all done with the sum, now check if it's divisible by 10
 *   while (sum>=0)
 *      sum = sum - 10;
 *   if (sum == 0)
 *       return 1;
 *   else
 *       return 0;
 */

checkCC:
	mov r1,#0		// sum = 0
	mov r3,#0		// pos = 0

ccNextDigit:
	ldrb r2,[r0,r3]	// fetch the next byte from the credit card string
	cmp  r2,#0
	beq  ccLastDigit	// branch away if we hit the last digit

	// if we get here, the digit is in r2, but it's still ASCII
	and  r2, r2, #0x0F	// only keep the number part, asciiToHex
	tst  r3,#1			// check for 0,2,4,6....position
	bne  ccEvenPosition

	lsl  r2,r2,#1		// r2 = r2 * 2
	cmp  r2,#10
	blo  ccOddPositionLow
	add  r2,r2,#1
ccOddPositionLow:
ccEvenPosition:
	add  r1,r1,r2			// sum = sum + c
	add  r3,r3,#1			// pos++
	b    ccNextDigit

ccLastDigit:
	subs r1,r1,#10			// sum = sum - 10
	bhi  ccLastDigit		// until it is zero or negative

	beq  ccOK
	mov  r0,#0
	bx   lr
ccOK:
    mov  r0,#1
    bx   lr

card1:	.asciz "4505590000088379"
card2:	.asciz "4505590000088378"

