MAP27 and CRC in asm [solved]

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all

I'm trying to emulate a radio control head (for a Simoco SRM9000) which communicates via MAP27. I'm having some trouble trying to achieve it. I think my main problem is calculating the CRC. I found a CRC routine in the library here, but it produces very different results to what I'm expecting. Even the lookup table it uses is different to the one in the MAP27 spec. I tried changing the tables over but I still get different results.

Does anyone have any experience with CRC or MAP27 in assembly? I see there is a MAP27 protocol in the libraries too, but alas it's in C. I guess the other options is to finally learn how to combine C and ASM.

Here's the asm library code I found to generate the CRC.

;			**********************************
;			*                                *
;			*    Fast lookup table driven    *
;			*     16 bit CRC Routine for     *
;			*   ATMEL AVR microcontrollers   *
;			*                                *
;			*          17-Oct-2002           *
;			*                                *
;			*       By Anthony Barrett       *
;			*                                *
;			**********************************
;
; Y (r28, R29) points to data in SRAM, r18 = data size in bytes.
; CRC result is returned in r16 (low byte) & r17 (high byte).
; Uses regisisters: r0, r1, r2, r16, r17, r18, r19, r28, r29, r30, r31 

Calc16CRC:		

	push	R0
	push	R1
	push	R2
	push	R19
	push	R30
	push	R31

	clr		r16
	clr		r17
	clr		r1

CRCLoop:
	ld		r2,		Y+
	mov		r19,	r17
	eor		r19,	r2
	ldi		ZL,		low(2 * CRC16Tab)
	ldi		ZH,		high(2 * CRC16Tab)
	add		ZL,		r19
	adc		ZH,		r1
	add		ZL,		r19
	adc		ZH,		r1
	lpm
	mov		r17,	r16
	mov		r16,	r0
	adiw	ZL,		1
	lpm
	eor		r17,	r0
	dec		r18
	brne	CRCLoop

	pop		R31
	pop		R30
	pop		R19
	pop		R2
	pop		R1
	pop		R0

	ret

;High speed 16 bit CRC lookup table:
;Polynomial: x^12 + x^5 + 1

CRC16Tab:
;this table comes from the MAP27 spec sheet v1.5
.dw $0000, $C1C0, $81C1, $4001, $01C3, $C003, $8002, $41C2, $01C6, $C006, $8007, $41C7, $0005, $C1C5, $81C4, $4004
.dw $01CC, $C00C, $800D, $41CD, $000F, $C1CF, $81CE, $400E, $000A, $C1CA, $81CB, $400B, $01C9, $C009, $8008, $41C8
.dw $01D8, $C018, $8019, $41D9, $001B, $C1DB, $81DA, $401A, $001E, $C1DE, $81DF, $401F, $01DD, $C01D, $801C, $41DC
.dw $0014, $C1D4, $81D5, $4015, $01D7, $C017, $8016, $41D6, $01D2, $C012, $8013, $41D3, $0011, $C1D1, $81D0, $4010
.dw $01F0, $C030, $8031, $41F1, $0033, $C1F3, $81F2, $4032, $0036, $C1F6, $81F7, $4037, $01F5, $C035, $8034, $41F4
.dw $003C, $C1FC, $81FD, $403D, $01FF, $C03F, $803E, $41FE, $01FA, $C03A, $803B, $41FB, $0039, $C1F9, $81F8, $4038
.dw $0028, $C1E8, $81E9, $4029, $01EB, $C02B, $802A, $41EA, $01EE, $C02E, $802F, $41EF, $002D, $C1ED, $81EC, $402C
.dw $01E4, $C024, $8025, $41E5, $0027, $C1E7, $81E6, $4026, $0022, $C1E2, $81E3, $4023, $01E1, $C021, $8020, $41E0
.dw $01A0, $C060, $8061, $41A1, $0063, $C1A3, $81A2, $4062, $0066, $C1A6, $81A7, $4067, $01A5, $C065, $8064, $41A4
.dw $006C, $C1AC, $81AD, $406D, $01AF, $C06F, $806E, $41AE, $01AA, $C06A, $806B, $41AB, $0069, $C1A9, $81A8, $4068
.dw $0078, $C1B8, $81B9, $4079, $01BB, $C07B, $807A, $41BA, $01BE, $C07E, $807F, $41BF, $007D, $C1BD, $81BC, $407C
.dw $01B4, $C074, $8075, $41B5, $0077, $C1B7, $81B6, $4076, $0072, $C1B2, $81B3, $4073, $01B1, $C071, $8070, $41B0
.dw $0050, $C190, $8191, $4051, $0193, $C053, $8052, $4192, $0196, $C056, $8057, $4197, $0055, $C195, $8194, $4054
.dw $019C, $C05C, $805D, $419D, $005F, $C19F, $819E, $405E, $005A, $C19A, $819B, $405B, $0199, $C059, $8058, $4198
.dw $0188, $C048, $8049, $4189, $004B, $C18B, $818A, $404A, $004E, $C18E, $818F, $404F, $018D, $C04D, $804C, $418C
.dw $0044, $C184, $8185, $4045, $0187, $C047, $8046, $4186, $0182, $C042, $8043, $4183, $0041, $C181, $8180, $4040

And my function calling it.

	ldi		YL,	low(TX_BUFFER)
	ldi		YH,	high(TX_BUFFER)		; load pointer to data buffer

	ldi		TEMP, $02
	st		Y+,	TEMP
	ldi		TEMP, $01
	st		Y+,	TEMP
	ldi		TEMP, $01
	st		Y+,	TEMP
	ldi		TEMP, $00
	st		Y+,	TEMP
	ldi		TEMP, $10
	st		Y+,	TEMP
	ldi		TEMP, $03
	st		Y+,	TEMP

	ldi		YL,	low(TX_BUFFER)
	ldi		YH,	high(TX_BUFFER)		; load pointer to data buffer
	ldi		R18,	$06				; load number of bytes in buffer
	rcall	Calc16CRC				; calculate CRC

In my code, I've stored some values manually in RAM. The CRC result should be $8F $FB, but the result I'm getting according to the simulator is $70 $1F.

Cheers in advance - Matt

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

from your code : ;Polynomial: x^12 + x^5 + 1

from what I get from this link:
http://www.mpt1327-usa.org/downloads/map27.pdf
-> G(x) = x16 + x15 + x2 + 1.

It might be that you have a different document, but this was the first one I stubled upon when searching for "map27 protocol"

so perhaps that helps you along ( or makes the confusion even bigger)

regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi meslomp

Thanks for looking. I think the different polynomial is why the sample had a different lookup table. Sorry I had changed the table but missed the comment on which polynomial it was. I think though that the rest of the instructions would be the same though... I think...

I've tried going through the MAP27 protocol document (the same one in the link above) and I've got a routine that works for their sample given, but it is only for 1 byte. When I try it for multiple bytes I get different results.

Here is my new code for the CRC:

; Y (R28, R29) points to data in SRAM, R18 = data size in bytes.
; CRC result is returned in R16 (low byte) & R17 (high byte).
; Uses regisisters: r0, r1, r2, r16, r17, r18, r19, r28, r29, r30, r31 

MATTCRC:

	push	R0
	push	R1
	push	R2
	push	R19
	push	R30
	push	R31

	ser		R16		;FCS Low
	ser		R17		;FCS High
	clr		R2		;constant $00 for adc command

MATTCRCLoop:
	ld		R19,	Y+		; load next byte to protect
	eor		R19,	R17		; eor it to previous address value

	ldi		ZL,		low(2 * CRC16Tab)	; load start of lookup table
	ldi		ZH,		high(2 * CRC16Tab)
	add		ZL,		R19		; add offset
	adc		ZH,		R2
	add		ZL,		R19		; do twice for word address
	adc		ZH,		R2
	lpm						; load LSB table value
	mov		R1,		R0		; save copy
	adiw    ZL,		1		; inc table pointer
	lpm						; load MSB table value
;R0 (MSB) and R1 (LSB) now contain table value

	eor		R16,	R0		; add FCS LSB with Table MSB
	mov		R17,	R16		; LSB becomes MSB
	com		R17				; MSB now done
	mov		R16,	R1		; copy LSB
	com		R16				; LSB now done

	dec		R18				; dec byte counter
	brne	MATTCRCLoop		; loop till done

	pop		R31
	pop		R30
	pop		R19
	pop		R2
	pop		R1
	pop		R0

	ret
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it has been a while since I did assembly, but are you sure you get the right int from the datatable?

as there is no externel electronics involved, perhaps it is a good time to run the simulator on this part of code to see where things go different then you expect.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got the checksum going now. I have some captures from real world usage so I've been able to compare several packets to check.

I'm still trying to get the whole protocol working, but that's another story.

Cheers - Matt

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know that these thread is old,  but it may help,  a MAP27 protocol implementation can be found: https://github.com/hemonserrat/m...

Anyone is welcome to contribute.

 

Cheers,

Hernan