EDC15 Multimap
Hope this helps anyone, although there doesnt seem to be much interest in this ECU... Follow my other post and disable the checksums first. 1st step is to find how the CANBUS is handled. There is a buffer in RAM in which the messages are stored before they are transmitted. On edc15, finding the buffer is easy. Example: Search for sequence of bytes: 0x280 or 0x288 or any other CAN id used by the ecu... This will point you to the code which handles canbus: Code: ROM:00094156 mov r5, #280h ROM:0009415A mov CAN_280, r5 ;CAN_280- RAM buffer handling id -0x280 ROM:0009415E movb rl4, #8 ROM:00094160 movb byte_C743, rl4 ROM:00094164 mov r4, #288h ROM:00094168 mov CAN_288, r4 ROM:0009416C movb rl4, #8 ROM:0009416E movb byte_C74F, rl4 ROM:00094172 mov r4, #380h ROM:00094176 mov CAN_380, r4 ROM:0009417A movb rl4, #8 ROM:0009417C movb byte_C75B, rl4 ROM:00094180 mov r4, #480h Now that you've found the CAN buffer, refer to the FR CAN section. Below, Ive shown the CANBUS buffer handling id 0x280 in my file. Code: MEM_EXT:0000C744 CAN_280: ds 2 ; DATA XREF: ROM:0009415Aw MEM_EXT:0000C746 byte_C746: ds 1 ; DATA XREF: ROM:000945DCw MEM_EXT:0000C746 ; ROM:0009463Ew ... MEM_EXT:0000C747 byte_C747: ds 1 ; DATA XREF: ROM:0009468Aw MEM_EXT:0000C747 ; ROM:0009475Ew MEM_EXT:0000C748 can_nmot_low: ds 1 ; DATA XREF: ROM:0009468Ew MEM_EXT:0000C748 ; ROM:00094788w MEM_EXT:0000C749 can_nmot_high: ds 1 ; DATA XREF: ROM:00094692w MEM_EXT:0000C749 ; ROM:00094790w MEM_EXT:0000C74A byte_C74A: ds 1 ; DATA XREF: ROM:00094696w MEM_EXT:0000C74A ; ROM:00094814w ... MEM_EXT:0000C74B byte_C74B: ds 1 ; DATA XREF: ROM:loc_948A0w MEM_EXT:0000C74B ; ROM:000948CAw MEM_EXT:0000C74C byte_C74C: ds 1 ; DATA XREF: ROM:00094D2Ew MEM_EXT:0000C74C ; ROM:loc_94DB6w MEM_EXT:0000C74D byte_C74D: ds 1 ; DATA XREF: ROM:0009469Ew MEM_EXT:0000C74D ; ROM:000947E6w MEM_EXT:0000C74E byte_C74E: ds 1 ; DATA XREF: ROM:000945C0w MEM_EXT:0000C74F byte_C74F: ds 1 ; DATA XREF: ROM:0009416Ew To use the rpm gauge for showing the present map(or any other parameter like boost, SOI,etc), you'll have to modify the subroutine writing to bytes 3 and 4 of the CAN id 0x280. Code: ROM:00094780 calls 9, sub_94002 ROM:00094784 add r0, #4 ROM:00094786 mov r9, r4 ROM:00094788 movb can_nmot_low, rl4 ROM:0009478C mov r4, r9 ROM:0009478E ashr r4, #8 ROM:00094790 movb can_nmot_high, rl4 ROM:00094794 mov r1, word_C420 ROM:00094798 add r1, word_C426 ROM:0009479C cmp r1, word_F962 ROM:000947A0 jmpr cc_SGE, loc_947A6 ROM:000947A2 mov r9, r1 ROM:000947A4 jmpr cc_UC, loc_947AA r4 contains the actual RPM. We will modify this vaue to whatever we want; to show the map selected in our case. I inserted my call at 94784, to my routine. Its upto you to decide where to insert this call, but make sure you dont change the original logic. Next step is to take inputs like clutch, brake or cruise control. This can also be inferenced from the CAN buffer. example: id 0x280, byte 0, bit 4 is B_kuppl(clutch pedal). Find the code which writes to this bit, and you will find B_kuppl Code: ROM:00094EBC movb rl4, word_C49A+1 ROM:00094EC0 jmpr cc_NZ, loc_94ED0 ROM:00094EC2 mov r4, word_14D6 ROM:00094EC6 movb rl5, [r4] ROM:00094EC8 jmpr cc_NZ, loc_94ED0 ROM:00094ECA movb rl4, #8 ROM:00094ECC orb byte_C746, rl4 As seen in above code, 0xC94B contains the status of the clutch pedal. But this is not the global variable. I suppose, this is a temporary RAM address to which the clutch switch status is copied when this subroutine starts(so that as long as the subroutine is still being executed, any change in the clutch status will not be updated. Otherwise, it's possible that at the start of the subroutine the status of the clutch is different from that when the subroutine ends, resulting in unpredictable behaviour) Find the global variable by searching for xrefs to 0xc94b Code: ROM:0009433E movb rl2, byte_C370 ROM:00094342 movb word_C49A+1, rl2 0xc370 is the global variable for B_kuppl. Repeat this for other variables you want to use(cruise control status is on id 0x388/0x38A and brake pedals on 0x288) Now, for mapswitching, you need to change the DPP's Each datablock is referred using DPP0, DPP1 and DPP2. DPP3 is used for CAN. datablock 1: DPP0- 0x34 DPP1- 0x35 DPP2- 0x36 datablock 2: DPP0- 0x38 DPP1- 0x39 DPP2- 0x3A datablock 3: DPP0- 0x3C DPP1- 0x3D DPP2- 0x3E This is the code I use for switching between maps and displaying boost on RPM gauge. Code: $MOD167 ; Define C167 mode $SEGMENTED ; Segemented memory mode $CASE ; Symbols case sensitive $include (reg167.inc) NAME MINIMON ASSUME DPP3:system StackData0 SECTION DATA SYSSTACK ; Data Section to reserve ; Stack-Memory DSB 20H ; 32 Byte StackData0 ENDS ; End of Dummy-Section DriverCode0 SECTION CODE PUBLIC 'CDRIVER' DriverProc PROC FAR mov r4, 0xc036 ;boost shl r4,#2 movb rl1,0xc370 ;b_kuppl jnb r1.0, needle movb rl1,0xc379 ;cc_cancel toggle button jnb r1.0, xyz movb rl1,#1 movb 0xc76e,rl1 ;cc_off debounce jmpr cc_uc, needle xyz: movb rl1,0xc76e jmpr cc_z, needle movb rl1,#0 movb 0xc76e,rl1 movb rl1,0xc76f ;delay counter jmpr cc_nz, dpp movb rl1,#0x7f ; initialize delay counter so that r4 isnt updated by the ECU for atleast ~ 40ms * 0x7F= 5080ms ~ 5sec movb 0xc76f,rl1 jmpr cc_uc, needle dpp: cmp dpp0,#0x3c jmpr cc_eq, dppl mov dpp0,#0x3c mov dpp1,#0x3d mov dpp2,#0x3e jmpr cc_uc,needle dppl: mov dpp0,#0x34 mov dpp1,#0x35 mov dpp2,#0x36 needle: mov rl1,0xc76f jmpr cc_z,end1 subb rl1,#1 mov 0xc76f,rl1 cmp dpp0,#0x3c jmpr cc_ne, n1 mov r4,#0x2ee0 jmpr cc_uc, end1 n1: mov r4,#0x3e80 end1: add r0,#4 mov r9,r4 rets DriverProc ENDP DriverCode0 ENDS END I suggest writing your own code, as mine can be a bit difficult to follow Basically, my code does this: - check if clutch is pressed, if yes then continue. - check if cruice control cancel button is pressed. If yes, store 1 in a free ram byte ( lots of free ram in this ECU, 0xC820-0xC82F is free on all the edc15's I've worked on, enough for our small subroutine) and exit the subroutine This is done to "debounce" the button press (as long as the button is pressed, no change will take place) - check if the "debounce" ram byte is 1, if yes, set it to 0 and switch maps( by changing the DPP's) - To display the map selected understand how the rpm is displayed on the instrument cluster. Lets say you want the rpm needle to show 2000rpm. There is a factor of 4. So the transmitted CAN message for rpm is 2000*4= 8000 which corresponds to 0x1F40 in hex All we need to do is replace the value in r4 with the value you want to display. - Setup a counter for displaying the selected map. This is necessary because replacing r4 with the desired value once is not enough. The main loop takes around 40ms to execute. So after 40ms r4 will get overwritten by RPM and the needle will not show the value you wanted it to show. Look at my code for a better understanding... Compile using Uvision or a compiler of your choice. Load the output hex file into Winols, search where your code begins, and copy it to a free space in your flash. Then insert a call to your new function. I chose to insert my call at 0x94784(0x14784 in WinOLS) Free space in my file - 0x1A000 which translates to 0x9A000 Hence, opcode for call: DA 09 00 A0 I will be posting a part 2 showing how you can save the selected datablock over ignition cycles. Creditos: |
AVISO LEGAL Y EXENCIÓN DE RESPONSABILIDAD
El presente documento, contenido, material o información se proporciona única y exclusivamente con fines educativos e informativos. El autor no asume ninguna responsabilidad por el uso indebido, interpretación errónea o aplicación que terceros puedan hacer de la información aquí contenida.
Toda la información se ofrece "tal cual", sin garantías de ningún tipo, expresas o implícitas. El autor no será responsable, bajo ninguna circunstancia, de daños directos, indirectos, incidentales, consecuenciales o de cualquier otra naturaleza derivados del uso o la imposibilidad de uso de este contenido.
El usuario acepta que utiliza esta información bajo su propia responsabilidad, comprendiendo que el autor no asume compromiso alguno respecto a la exactitud, veracidad ni actualización de los datos, ejemplos o procedimientos expuestos. AVISO LEGAL Y EXENCIÓN DE RESPONSABILIDAD
El presente documento, contenido, material o información se proporciona única y exclusivamente con fines educativos e informativos. El autor no asume ninguna responsabilidad por el uso indebido, interpretación errónea o aplicación que terceros puedan hacer de la información aquí contenida.
Toda la información se ofrece "tal cual", sin garantías de ningún tipo, expresas o implícitas. El autor no será responsable, bajo ninguna circunstancia, de daños directos, indirectos, incidentales, consecuenciales o de cualquier otra naturaleza derivados del uso o la imposibilidad de uso de este contenido.
El usuario acepta que utiliza esta información bajo su propia responsabilidad, comprendiendo que el autor no asume compromiso alguno respecto a la exactitud, veracidad ni actualización de los datos, ejemplos o procedimientos expuestos. |
Comentarios
Publicar un comentario