@@ -50,6 +50,41 @@ static int countElements(char* buffer, int length) {
5050 return count ;
5151}
5252
53+ static FDCAN_TxHeaderTypeDef USBTxHeader ;
54+ static uint8_t USBTxData [8U ];
55+
56+ // Function to send a UDS frame based on provided CAN ID and ascii string
57+ void sendUDSAsciiHex (uint16_t can_id , char * ascii_hex )
58+ {
59+ uint8_t data [8 ] = {0 };
60+ uint8_t payload [7 ];
61+ uint8_t payload_len = 0 ;
62+
63+ while (* ascii_hex && * (ascii_hex + 1 ) && payload_len < 7 )
64+ {
65+ payload [payload_len ++ ] = ASCIItoUint8 (ascii_hex );
66+ ascii_hex += 2 ;
67+ }
68+
69+ data [0 ] = payload_len ;
70+
71+ for (uint8_t i = 0 ; i < payload_len ; i ++ )
72+ {
73+ data [i + 1 ] = payload [i ];
74+ }
75+
76+ /* Configure CAN header */
77+ USBTxHeader .BitRateSwitch = FDCAN_BRS_OFF ;
78+ USBTxHeader .FDFormat = FDCAN_CLASSIC_CAN ;
79+ USBTxHeader .TxFrameType = FDCAN_DATA_FRAME ;
80+ USBTxHeader .IdType = FDCAN_STANDARD_ID ;
81+ USBTxHeader .Identifier = can_id ;
82+ USBTxHeader .DataLength = UINT8toDLC (8 );
83+
84+ RAMN_memcpy ((uint8_t * )USBTxData , data , 8 );
85+ RAMN_FDCAN_SendMessage (& USBTxHeader , USBTxData );
86+ }
87+
5388RAMN_Bool_t RAMN_CDC_ProcessCLIBuffer (uint8_t * USBRxBuffer , uint32_t commandLength )
5489{
5590 // Command is in USBRxBuffer, length is in commandLength. There is no endline in buffer.
@@ -464,6 +499,137 @@ RAMN_Bool_t RAMN_CDC_ProcessCLIBuffer(uint8_t* USBRxBuffer, uint32_t commandLeng
464499 RAMN_FDCAN_ResetPeripheral ();
465500 }
466501 }
502+ else if (strcmp (token , "uds" ) == 0 ) {
503+ if (elementCount != 3 )
504+ {
505+ RAMN_USB_SendStringFromTask ("Usage: uds <B|C|D|*> <hex_payload>. Use * for broadcast.\r" );
506+ }
507+ else
508+ {
509+ uint16_t can_id = 0 ;
510+
511+ token = strtok (NULL , " " );
512+ can_id = 0 ;
513+ if (strcmp (token , "*" ) == 0 )
514+ {
515+ can_id = 0x7DF ;
516+ }
517+ else if (strcmp (token , "B" ) == 0 )
518+ {
519+ can_id = 0x7E1 ;
520+ }
521+ else if (strcmp (token , "C" ) == 0 )
522+ {
523+ can_id = 0x7E2 ;
524+ }
525+ else if (strcmp (token , "D" ) == 0 )
526+ {
527+ can_id = 0x7E3 ;
528+ }
529+ else if (strcmp (token , "A" ) == 0 )
530+ {
531+ RAMN_USB_SendStringFromTask ("Error: Use slcan to send UDS commands to ECU A.\r" );
532+ }
533+ else
534+ {
535+ RAMN_USB_SendStringFromTask ("Invalid ECU. Use B, C, D, or *.\r" );
536+ }
537+ if (0x7E1 != 0 )
538+ {
539+ token = strtok (NULL , " " );
540+
541+ uint16_t len = RAMN_strlen (token );
542+
543+ if ((len == 0 ) || (len % 2 != 0 ) || (len > 14 ))
544+ {
545+ RAMN_USB_SendStringFromTask ("Invalid payload. Must be 1-7 bytes hex.\r" );
546+ }
547+ else
548+ {
549+ sendUDSAsciiHex (can_id , token );
550+ }
551+ }
552+ }
553+ }
554+ else if (strcmp (token , "silence" ) == 0 ) {
555+
556+ if (elementCount != 2 )
557+ {
558+ RAMN_USB_SendStringFromTask ("Usage: silence <B|C|D|*>\r" );
559+ }
560+ else
561+ {
562+ token = strtok (NULL , " " );
563+
564+ for (uint8_t i = 0 ; ((token [i ] != 0 ) && (i < 4 )); i ++ )
565+ {
566+ switch (token [i ])
567+ {
568+ case '*' :
569+ RAMN_USB_SendStringFromTask ("Silencing all ECUs (broadcast).\r" );
570+ sendUDSAsciiHex (0x7DF , "31010200" );
571+ break ;
572+ case 'A' :
573+ RAMN_USB_SendStringFromTask ("ECU A does not support this command.\r" );
574+ break ;
575+ case 'B' :
576+ RAMN_USB_SendStringFromTask ("Silencing ECU B.\r" );
577+ sendUDSAsciiHex (0x7E1 , "31010200" );
578+ break ;
579+ case 'C' :
580+ RAMN_USB_SendStringFromTask ("Silencing ECU C.\r" );
581+ sendUDSAsciiHex (0x7E2 , "31010200" );
582+ break ;
583+ case 'D' :
584+ RAMN_USB_SendStringFromTask ("Silencing ECU D.\r" );
585+ sendUDSAsciiHex (0x7E3 , "31010200" );
586+ break ;
587+ default :
588+ RAMN_USB_SendStringFromTask ("Invalid ECU. Use B, C, D, or *.\r" );
589+ break ;
590+ }
591+ }
592+ }
593+ }
594+ else if (strcmp (token , "talk" ) == 0 ) {
595+ if (elementCount != 2 )
596+ {
597+ RAMN_USB_SendStringFromTask ("Usage: talk <B|C|D|*>\r" );
598+ }
599+ else
600+ {
601+ token = strtok (NULL , " " );
602+
603+ for (uint8_t i = 0 ; ((token [i ] != 0 ) && (i < 4 )); i ++ )
604+ {
605+ switch (token [i ])
606+ {
607+ case '*' :
608+ RAMN_USB_SendStringFromTask ("Restoring communication for all ECUs.\r" );
609+ sendUDSAsciiHex (0x7DF , "31020200" );
610+ break ;
611+ case 'A' :
612+ RAMN_USB_SendStringFromTask ("ECU A does not support this command.\r" );
613+ break ;
614+ case 'B' :
615+ RAMN_USB_SendStringFromTask ("Restoring ECU B communication.\r" );
616+ sendUDSAsciiHex (0x7E1 , "31020200" );
617+ break ;
618+ case 'C' :
619+ RAMN_USB_SendStringFromTask ("Restoring ECU C communication.\r" );
620+ sendUDSAsciiHex (0x7E2 , "31020200" );
621+ break ;
622+ case 'D' :
623+ RAMN_USB_SendStringFromTask ("Restoring ECU D communication.\r" );
624+ sendUDSAsciiHex (0x7E3 , "31020200" );
625+ break ;
626+ default :
627+ RAMN_USB_SendStringFromTask ("Invalid ECU. Use B, C, D, or *.\r" );
628+ break ;
629+ }
630+ }
631+ }
632+ }
467633#ifdef ENABLE_SCREEN
468634 else if ( strcmp (token , "theme ") == 0 ) {
469635 if (elementCount != 2 )
0 commit comments