1282e8f5a cap libusb1 version in setup (#183)
64bcc89a9 Subaru: 545 msg must be generated
9159df9a5 Merge branch '0.5.10-chyrsler'
f8ab74a1c L-line relay (#166)
11c4cdcc4 Cleanup leftover jenkins command
22572d949 Fix Jenkins build dockerfiles with same name
1d2f8f0ab Jenkins (#179)
f383eee96 Power saving: wake on RX and don't print durint IRQ
9540db744 Chrysler safety: better to mention messages we don't want to forward
104950264 chrysler: forward bus 0 to bus 2 (#177)
4276c380e Additional Power saving (#170)
git-subtree-dir: panda
git-subtree-split: 1282e8f5a0904b1aaa50f382db2e27f20e74a154
old-commit-hash: 3c25760cc9
			
			
				commatwo_master
			
			
		
							parent
							
								
									698871ecc7
								
							
						
					
					
						commit
						16dc094d4e
					
				
				 37 changed files with 947 additions and 107 deletions
			
			
		| @ -0,0 +1,3 @@ | |||||||
|  | .git | ||||||
|  | .DS_Store | ||||||
|  | boardesp/esp-open-sdk | ||||||
| @ -0,0 +1,64 @@ | |||||||
|  | FROM ubuntu:16.04 | ||||||
|  | ENV PYTHONUNBUFFERED 1 | ||||||
|  | 
 | ||||||
|  | RUN apt-get update && apt-get install -y \ | ||||||
|  |     autoconf \ | ||||||
|  |     automake \ | ||||||
|  |     bash \ | ||||||
|  |     bison \ | ||||||
|  |     bzip2 \ | ||||||
|  |     curl \ | ||||||
|  |     dfu-util \ | ||||||
|  |     flex \ | ||||||
|  |     g++ \ | ||||||
|  |     gawk \ | ||||||
|  |     gcc \ | ||||||
|  |     git \ | ||||||
|  |     gperf \ | ||||||
|  |     help2man \ | ||||||
|  |     iputils-ping \ | ||||||
|  |     libexpat-dev \ | ||||||
|  |     libstdc++-arm-none-eabi-newlib \ | ||||||
|  |     libtool \ | ||||||
|  |     libtool-bin \ | ||||||
|  |     libusb-1.0-0 \ | ||||||
|  |     make \ | ||||||
|  |     ncurses-dev \ | ||||||
|  |     network-manager \ | ||||||
|  |     python-dev \ | ||||||
|  |     python-serial \ | ||||||
|  |     sed \ | ||||||
|  |     texinfo \ | ||||||
|  |     unrar-free \ | ||||||
|  |     unzip \ | ||||||
|  |     wget \ | ||||||
|  |     build-essential \ | ||||||
|  |     python-dev \ | ||||||
|  |     python-pip \ | ||||||
|  |     screen \ | ||||||
|  |     vim \ | ||||||
|  |     wget \ | ||||||
|  |     wireless-tools | ||||||
|  | 
 | ||||||
|  | RUN pip install --upgrade pip==18.0 | ||||||
|  | 
 | ||||||
|  | COPY requirements.txt /tmp/ | ||||||
|  | RUN pip install -r /tmp/requirements.txt | ||||||
|  | 
 | ||||||
|  | RUN mkdir -p /home/batman | ||||||
|  | ENV HOME /home/batman | ||||||
|  | 
 | ||||||
|  | ENV PYTHONPATH /tmp:$PYTHONPATH | ||||||
|  | 
 | ||||||
|  | COPY ./boardesp/get_sdk_ci.sh /tmp/panda/boardesp/ | ||||||
|  | 
 | ||||||
|  | RUN useradd --system -s /sbin/nologin pandauser | ||||||
|  | RUN mkdir -p /tmp/panda/boardesp/esp-open-sdk | ||||||
|  | RUN chown pandauser /tmp/panda/boardesp/esp-open-sdk | ||||||
|  | USER pandauser | ||||||
|  | RUN cd /tmp/panda/boardesp && ./get_sdk_ci.sh | ||||||
|  | USER root | ||||||
|  | 
 | ||||||
|  | COPY ./xx/pandaextra /tmp/pandaextra | ||||||
|  | 
 | ||||||
|  | ADD ./panda.tar.gz /tmp/panda | ||||||
| @ -0,0 +1,55 @@ | |||||||
|  | pipeline { | ||||||
|  |   agent any | ||||||
|  |   environment { | ||||||
|  |     AUTHOR = """${sh( | ||||||
|  |                 returnStdout: true, | ||||||
|  |                 script: "git --no-pager show -s --format='%an' ${GIT_COMMIT}" | ||||||
|  |              ).trim()}""" | ||||||
|  | 
 | ||||||
|  |     DOCKER_IMAGE_TAG = "panda:build-${env.BUILD_ID}" | ||||||
|  |     DOCKER_NAME = "panda-test-${env.BUILD_ID}" | ||||||
|  |   } | ||||||
|  |   stages { | ||||||
|  |     stage('Build Docker Image') { | ||||||
|  |       steps { | ||||||
|  |         timeout(time: 60, unit: 'MINUTES') { | ||||||
|  |           script { | ||||||
|  |             sh 'git clone --no-checkout --depth 1 git@github.com:commaai/xx.git || true' | ||||||
|  |             sh 'cd xx && git fetch origin && git checkout origin/master -- pandaextra && cd ..' // Needed for certs for panda flashing | ||||||
|  |             sh 'git archive -v -o panda.tar.gz --format=tar.gz HEAD' | ||||||
|  |             dockerImage = docker.build("${env.DOCKER_IMAGE_TAG}") | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     stage('Test Dev Build') { | ||||||
|  |       steps { | ||||||
|  |         lock(resource: "Pandas", inversePrecedence: true, quantity:1){ | ||||||
|  |           timeout(time: 60, unit: 'MINUTES') { | ||||||
|  |             sh "docker run --name ${env.DOCKER_NAME} --privileged --volume /dev/bus/usb:/dev/bus/usb --volume /var/run/dbus:/var/run/dbus --net host ${env.DOCKER_IMAGE_TAG} bash -c 'cd /tmp/panda; ./run_automated_tests.sh '" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     stage('Test EON Build') { | ||||||
|  |       steps { | ||||||
|  |         lock(resource: "Pandas", inversePrecedence: true, quantity:1){ | ||||||
|  |           timeout(time: 60, unit: 'MINUTES') { | ||||||
|  |             sh "docker cp ${env.DOCKER_NAME}:/tmp/panda/nosetests.xml test_results_dev.xml" | ||||||
|  |             sh "touch EON && docker cp EON ${env.DOCKER_NAME}:/EON" | ||||||
|  |             sh "docker start -a ${env.DOCKER_NAME}" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   post { | ||||||
|  |     always { | ||||||
|  |       script { | ||||||
|  |         sh "docker cp ${env.DOCKER_NAME}:/tmp/panda/nosetests.xml test_results_EON.xml" | ||||||
|  |         sh "docker rm ${env.DOCKER_NAME}" | ||||||
|  |       } | ||||||
|  |       junit "test_results*.xml" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,88 @@ | |||||||
|  | #ifdef PANDA | ||||||
|  | 
 | ||||||
|  | int relay_control = 0;  // True if relay is controlled through l-line
 | ||||||
|  | 
 | ||||||
|  | /* Conrol a relay connected to l-line pin */ | ||||||
|  | 
 | ||||||
|  | // 160us cycles, 1 high, 25 low
 | ||||||
|  | 
 | ||||||
|  | volatile int turn_on_relay = 0; | ||||||
|  | volatile int on_cycles = 25; | ||||||
|  | 
 | ||||||
|  | //5s timeout
 | ||||||
|  | #define LLINE_TIMEOUT_CYCLES 31250 | ||||||
|  | volatile int timeout_cycles = LLINE_TIMEOUT_CYCLES; | ||||||
|  | 
 | ||||||
|  | void TIM5_IRQHandler(void) { | ||||||
|  |   if (TIM5->SR & TIM_SR_UIF) { | ||||||
|  |     on_cycles--; | ||||||
|  |     timeout_cycles--; | ||||||
|  |     if (timeout_cycles == 0) { | ||||||
|  |       turn_on_relay = 0; | ||||||
|  |     } | ||||||
|  |     if (on_cycles > 0) { | ||||||
|  |       if (turn_on_relay) { | ||||||
|  |         set_gpio_output(GPIOC, 10, 0); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       set_gpio_output(GPIOC, 10, 1); | ||||||
|  |       on_cycles = 25; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   TIM5->ARR = 160-1; | ||||||
|  |   TIM5->SR = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void lline_relay_init (void) { | ||||||
|  |   set_lline_output(0); | ||||||
|  |   relay_control = 1; | ||||||
|  |   set_gpio_output(GPIOC, 10, 1); | ||||||
|  | 
 | ||||||
|  |   // setup
 | ||||||
|  |   TIM5->PSC = 48-1; // tick on 1 us
 | ||||||
|  |   TIM5->CR1 = TIM_CR1_CEN;   // enable
 | ||||||
|  |   TIM5->ARR = 50-1;         // 50 us
 | ||||||
|  |   TIM5->DIER = TIM_DIER_UIE; // update interrupt
 | ||||||
|  |   TIM5->CNT = 0; | ||||||
|  | 
 | ||||||
|  |   NVIC_EnableIRQ(TIM5_IRQn); | ||||||
|  | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   puts("INIT LLINE\n"); | ||||||
|  |   puts(" SR "); | ||||||
|  |   putui(TIM5->SR); | ||||||
|  |   puts(" PSC "); | ||||||
|  |   putui(TIM5->PSC); | ||||||
|  |   puts(" CR1 "); | ||||||
|  |   putui(TIM5->CR1); | ||||||
|  |   puts(" ARR "); | ||||||
|  |   putui(TIM5->ARR); | ||||||
|  |   puts(" DIER "); | ||||||
|  |   putui(TIM5->DIER); | ||||||
|  |   puts(" SR "); | ||||||
|  |   putui(TIM5->SR); | ||||||
|  |   puts(" CNT "); | ||||||
|  |   putui(TIM5->CNT); | ||||||
|  |   puts("\n"); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void lline_relay_release (void) { | ||||||
|  |   set_lline_output(0); | ||||||
|  |   relay_control = 0; | ||||||
|  |   puts("RELEASE LLINE\n"); | ||||||
|  |   set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); | ||||||
|  |   NVIC_DisableIRQ(TIM5_IRQn); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void set_lline_output(int to_set) { | ||||||
|  |   timeout_cycles = LLINE_TIMEOUT_CYCLES; | ||||||
|  |   turn_on_relay = to_set; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int get_lline_status() { | ||||||
|  |   return turn_on_relay; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -0,0 +1,157 @@ | |||||||
|  | #define POWER_SAVE_STATUS_DISABLED 0 | ||||||
|  | //Moving to enabled, but can wakeup not yet enabled
 | ||||||
|  | #define POWER_SAVE_STATUS_SWITCHING 1 | ||||||
|  | #define POWER_SAVE_STATUS_ENABLED 2 | ||||||
|  | 
 | ||||||
|  | volatile int power_save_status = POWER_SAVE_STATUS_DISABLED; | ||||||
|  | 
 | ||||||
|  | void power_save_enable(void) { | ||||||
|  |   power_save_status = POWER_SAVE_STATUS_SWITCHING; | ||||||
|  |   puts("Saving power\n"); | ||||||
|  |   //Turn off can transciever
 | ||||||
|  |   set_can_enable(CAN1, 0); | ||||||
|  |   set_can_enable(CAN2, 0); | ||||||
|  | #ifdef PANDA | ||||||
|  |   set_can_enable(CAN3, 0); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   //Turn off GMLAN
 | ||||||
|  |   set_gpio_output(GPIOB, 14, 0); | ||||||
|  |   set_gpio_output(GPIOB, 15, 0); | ||||||
|  | 
 | ||||||
|  | #ifdef PANDA | ||||||
|  |   //Turn off LIN K
 | ||||||
|  |   if (revision == PANDA_REV_C) { | ||||||
|  |     set_gpio_output(GPIOB, 7, 0); // REV C
 | ||||||
|  |   } else { | ||||||
|  |     set_gpio_output(GPIOB, 4, 0); // REV AB
 | ||||||
|  |   } | ||||||
|  |   // LIN L
 | ||||||
|  |   set_gpio_output(GPIOA, 14, 0); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   if (is_grey_panda) { | ||||||
|  |     char* UBLOX_SLEEP_MSG = "\xb5\x62\x06\x04\x04\x00\x01\x00\x08\x00\x17\x78"; | ||||||
|  |     int len = 12; | ||||||
|  |     uart_ring *ur = get_ring_by_number(1); | ||||||
|  |     for (int i = 0; i < len; i++) while (!putc(ur, UBLOX_SLEEP_MSG[i])); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   //Setup timer for can enable
 | ||||||
|  |   TIM6->PSC = 48-1; // tick on 1 us
 | ||||||
|  | 
 | ||||||
|  |   TIM6->ARR = 12; // 12us
 | ||||||
|  |   // Enable, One-Pulse Mode, Only overflow interrupt
 | ||||||
|  |   TIM6->CR1 = TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS; | ||||||
|  |   TIM6->EGR = TIM_EGR_UG; | ||||||
|  |   TIM6->CR1 |= TIM_CR1_CEN; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void power_save_enable_can_wake(void) { | ||||||
|  |   // CAN Automatic Wake must be done a little while after the sleep
 | ||||||
|  |   // On some cars turning off the can transciver can trigger the wakeup
 | ||||||
|  |   power_save_status = POWER_SAVE_STATUS_ENABLED; | ||||||
|  |   puts("Turning can off\n"); | ||||||
|  |   CAN1->MCR |= CAN_MCR_SLEEP; | ||||||
|  |   CAN1->MCR |= CAN_MCR_AWUM; | ||||||
|  | 
 | ||||||
|  |   CAN2->MCR |= CAN_MCR_SLEEP; | ||||||
|  |   CAN2->MCR |= CAN_MCR_AWUM; | ||||||
|  | #ifdef PANDA | ||||||
|  |   CAN3->MCR |= CAN_MCR_SLEEP; | ||||||
|  |   CAN3->MCR |= CAN_MCR_AWUM; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   //set timer back
 | ||||||
|  |   TIM6->PSC = 48000-1; // tick on 1 ms
 | ||||||
|  |   TIM6->ARR = 10000; // 10s
 | ||||||
|  |   // Enable, One-Pulse Mode, Only overflow interrupt
 | ||||||
|  |   TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_URS; | ||||||
|  |   TIM6->EGR = TIM_EGR_UG; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void power_save_disable(void) { | ||||||
|  |   power_save_status = POWER_SAVE_STATUS_DISABLED; | ||||||
|  |   puts("not Saving power\n"); | ||||||
|  |   TIM6->CR1 |= TIM_CR1_CEN; //Restart timer
 | ||||||
|  |   TIM6->CNT = 0; | ||||||
|  | 
 | ||||||
|  |   //Turn on can
 | ||||||
|  |   set_can_enable(CAN1, 1); | ||||||
|  |   set_can_enable(CAN2, 1); | ||||||
|  | 
 | ||||||
|  | #ifdef PANDA | ||||||
|  |   set_can_enable(CAN3, 1); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   //Turn on GMLAN
 | ||||||
|  |   set_gpio_output(GPIOB, 14, 1); | ||||||
|  |   set_gpio_output(GPIOB, 15, 1); | ||||||
|  | 
 | ||||||
|  | #ifdef PANDA | ||||||
|  |   //Turn on LIN K
 | ||||||
|  |   if (revision == PANDA_REV_C) { | ||||||
|  |     set_gpio_output(GPIOB, 7, 1); // REV C
 | ||||||
|  |   } else { | ||||||
|  |     set_gpio_output(GPIOB, 4, 1); // REV AB
 | ||||||
|  |   } | ||||||
|  |   // LIN L
 | ||||||
|  |   set_gpio_output(GPIOA, 14, 1); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   if (is_grey_panda) { | ||||||
|  |     char* UBLOX_WAKE_MSG = "\xb5\x62\x06\x04\x04\x00\x01\x00\x09\x00\x18\x7a"; | ||||||
|  |     int len = 12; | ||||||
|  |     uart_ring *ur = get_ring_by_number(1); | ||||||
|  |     for (int i = 0; i < len; i++) while (!putc(ur, UBLOX_WAKE_MSG[i])); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   //set timer back
 | ||||||
|  |   TIM6->PSC = 48000-1; // tick on 1 ms
 | ||||||
|  |   TIM6->ARR = 10000; // 10s
 | ||||||
|  |   // Enable, One-Pulse Mode, Only overflow interrupt
 | ||||||
|  |   TIM6->CR1 = TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS; | ||||||
|  |   TIM6->EGR = TIM_EGR_UG; | ||||||
|  |   TIM6->CR1 |= TIM_CR1_CEN; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Reset timer when activity
 | ||||||
|  | void power_save_reset_timer() { | ||||||
|  |   TIM6->CNT = 0; | ||||||
|  |   if (power_save_status != POWER_SAVE_STATUS_DISABLED){ | ||||||
|  |     power_save_disable(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void power_save_init(void) { | ||||||
|  |   puts("Saving power init\n"); | ||||||
|  |   TIM6->PSC = 48000-1; // tick on 1 ms
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   TIM6->ARR = 10000; // 10s
 | ||||||
|  |   // Enable, One-Pulse Mode, Only overflow interrupt
 | ||||||
|  |   TIM6->CR1 = TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS; | ||||||
|  |   TIM6->EGR = TIM_EGR_UG; | ||||||
|  |   NVIC_EnableIRQ(TIM6_DAC_IRQn); | ||||||
|  |   puts("Saving power init done\n"); | ||||||
|  |   TIM6->DIER = TIM_DIER_UIE; | ||||||
|  |   TIM6->CR1 |= TIM_CR1_CEN; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void TIM6_DAC_IRQHandler(void) { | ||||||
|  |   //Timeout switch to power saving mode.
 | ||||||
|  |   if (TIM6->SR & TIM_SR_UIF) { | ||||||
|  |     TIM6->SR = 0; | ||||||
|  | #ifdef EON | ||||||
|  |     if (power_save_status == POWER_SAVE_STATUS_DISABLED) { | ||||||
|  |       power_save_enable(); | ||||||
|  |     } else if (power_save_status == POWER_SAVE_STATUS_SWITCHING) { | ||||||
|  |       power_save_enable_can_wake(); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |   } else { | ||||||
|  |     TIM6->CR1 |= TIM_CR1_CEN; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | git clone --recursive https://github.com/pfalcon/esp-open-sdk.git | ||||||
|  | cd esp-open-sdk | ||||||
|  | git checkout 03f5e898a059451ec5f3de30e7feff30455f7cec | ||||||
|  | LD_LIBRARY_PATH="" make STANDALONE=y | ||||||
| @ -1,4 +1,7 @@ | |||||||
| libusb1 | libusb1 == 1.6.6 | ||||||
| hexdump | hexdump | ||||||
| pycrypto | pycrypto | ||||||
| tqdm | tqdm | ||||||
|  | nose | ||||||
|  | parameterized | ||||||
|  | requests | ||||||
|  | |||||||
| @ -1,3 +1,9 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
| PYTHONPATH="." nosetests -x -s tests/automated/$1*.py | TEST_FILENAME=${TEST_FILENAME:-nosetests.xml} | ||||||
|  | if [ ! -f "/EON" ]; then | ||||||
|  |   TESTSUITE_NAME="Panda_Test-EON" | ||||||
|  | else | ||||||
|  |   TESTSUITE_NAME="Panda_Test-DEV" | ||||||
|  | fi | ||||||
| 
 | 
 | ||||||
|  | PYTHONPATH="." nosetests -v --with-xunit --xunit-file=./$TEST_FILENAME --xunit-testsuite-name=$TESTSUITE_NAME -s tests/automated/$1*.py | ||||||
|  | |||||||
| @ -0,0 +1,121 @@ | |||||||
|  | from __future__ import print_function | ||||||
|  | import time | ||||||
|  | from panda import Panda | ||||||
|  | from nose.tools import assert_equal, assert_less, assert_greater | ||||||
|  | from helpers import time_many_sends, test_two_panda, panda_color_to_serial | ||||||
|  | 
 | ||||||
|  | @test_two_panda | ||||||
|  | @panda_color_to_serial | ||||||
|  | def test_send_recv(serial_sender=None, serial_reciever=None): | ||||||
|  |   p_send = Panda(serial_sender) | ||||||
|  |   p_recv = Panda(serial_reciever) | ||||||
|  | 
 | ||||||
|  |   p_send.set_safety_mode(Panda.SAFETY_ALLOUTPUT) | ||||||
|  |   p_send.set_can_loopback(False) | ||||||
|  | 
 | ||||||
|  |   p_recv.set_can_loopback(False) | ||||||
|  | 
 | ||||||
|  |   assert not p_send.legacy | ||||||
|  |   assert not p_recv.legacy | ||||||
|  | 
 | ||||||
|  |   p_send.can_send_many([(0x1ba, 0, "message", 0)]*2) | ||||||
|  |   time.sleep(0.05) | ||||||
|  |   p_recv.can_recv() | ||||||
|  |   p_send.can_recv() | ||||||
|  | 
 | ||||||
|  |   busses = [0,1,2] | ||||||
|  | 
 | ||||||
|  |   for bus in busses: | ||||||
|  |     for speed in [100, 250, 500, 750, 1000]: | ||||||
|  |       p_send.set_can_speed_kbps(bus, speed) | ||||||
|  |       p_recv.set_can_speed_kbps(bus, speed) | ||||||
|  |       time.sleep(0.05) | ||||||
|  | 
 | ||||||
|  |       comp_kbps = time_many_sends(p_send, bus, p_recv, two_pandas=True) | ||||||
|  | 
 | ||||||
|  |       saturation_pct = (comp_kbps/speed) * 100.0 | ||||||
|  |       assert_greater(saturation_pct, 80) | ||||||
|  |       assert_less(saturation_pct, 100) | ||||||
|  | 
 | ||||||
|  |       print("two pandas bus {}, 100 messages at speed {:4d}, comp speed is {:7.2f}, percent {:6.2f}".format(bus, speed, comp_kbps, saturation_pct)) | ||||||
|  | 
 | ||||||
|  | @test_two_panda | ||||||
|  | @panda_color_to_serial | ||||||
|  | def test_latency(serial_sender=None, serial_reciever=None): | ||||||
|  |   p_send = Panda(serial_sender) | ||||||
|  |   p_recv = Panda(serial_reciever) | ||||||
|  | 
 | ||||||
|  |   p_send.set_safety_mode(Panda.SAFETY_ALLOUTPUT) | ||||||
|  |   p_send.set_can_loopback(False) | ||||||
|  | 
 | ||||||
|  |   p_recv.set_can_loopback(False) | ||||||
|  | 
 | ||||||
|  |   assert not p_send.legacy | ||||||
|  |   assert not p_recv.legacy | ||||||
|  | 
 | ||||||
|  |   p_send.set_can_speed_kbps(0, 100) | ||||||
|  |   p_recv.set_can_speed_kbps(0, 100) | ||||||
|  |   time.sleep(0.05) | ||||||
|  | 
 | ||||||
|  |   p_send.can_send_many([(0x1ba, 0, "testmsg", 0)]*10) | ||||||
|  |   time.sleep(0.05) | ||||||
|  |   p_recv.can_recv() | ||||||
|  |   p_send.can_recv() | ||||||
|  | 
 | ||||||
|  |   busses = [0,1,2] | ||||||
|  | 
 | ||||||
|  |   for bus in busses: | ||||||
|  |     for speed in [100, 250, 500, 750, 1000]: | ||||||
|  |       p_send.set_can_speed_kbps(bus, speed) | ||||||
|  |       p_recv.set_can_speed_kbps(bus, speed) | ||||||
|  |       time.sleep(0.1) | ||||||
|  |       #clear can buffers | ||||||
|  |       r = [1] | ||||||
|  |       while len(r) > 0: | ||||||
|  |         r = p_send.can_recv() | ||||||
|  |       r = [1] | ||||||
|  |       while len(r) > 0: | ||||||
|  |         r = p_recv.can_recv() | ||||||
|  |       time.sleep(0.05) | ||||||
|  | 
 | ||||||
|  |       latencies = [] | ||||||
|  |       comp_kbps_list = [] | ||||||
|  |       saturation_pcts = [] | ||||||
|  | 
 | ||||||
|  |       num_messages = 100 | ||||||
|  | 
 | ||||||
|  |       for i in range(num_messages): | ||||||
|  |         st = time.time() | ||||||
|  |         p_send.can_send(0x1ab, "message", bus) | ||||||
|  |         r = [] | ||||||
|  |         while len(r) < 1 and (time.time() - st) < 5: | ||||||
|  |           r = p_recv.can_recv() | ||||||
|  |         et = time.time() | ||||||
|  |         r_echo = [] | ||||||
|  |         while len(r_echo) < 1 and (time.time() - st) < 10: | ||||||
|  |           r_echo = p_send.can_recv() | ||||||
|  | 
 | ||||||
|  |         if len(r) == 0 or len(r_echo) == 0: | ||||||
|  |           print("r: {}, r_echo: {}".format(r, r_echo)) | ||||||
|  | 
 | ||||||
|  |         assert_equal(len(r),1) | ||||||
|  |         assert_equal(len(r_echo),1) | ||||||
|  | 
 | ||||||
|  |         et = (et - st)*1000.0 | ||||||
|  |         comp_kbps = (1+11+1+1+1+4+8*8+15+1+1+1+7) / et | ||||||
|  |         latency = et - ((1+11+1+1+1+4+8*8+15+1+1+1+7) / speed) | ||||||
|  | 
 | ||||||
|  |         assert_less(latency, 5.0) | ||||||
|  | 
 | ||||||
|  |         saturation_pct = (comp_kbps/speed) * 100.0 | ||||||
|  |         latencies.append(latency) | ||||||
|  |         comp_kbps_list.append(comp_kbps) | ||||||
|  |         saturation_pcts.append(saturation_pct) | ||||||
|  | 
 | ||||||
|  |       average_latency = sum(latencies)/num_messages | ||||||
|  |       assert_less(average_latency, 1.0) | ||||||
|  |       average_comp_kbps = sum(comp_kbps_list)/num_messages | ||||||
|  |       average_saturation_pct = sum(saturation_pcts)/num_messages | ||||||
|  | 
 | ||||||
|  |       print("two pandas bus {}, {} message average at speed {:4d}, latency is {:5.3f}ms, comp speed is {:7.2f}, percent {:6.2f}"\ | ||||||
|  |             .format(bus, num_messages, speed, average_latency, average_comp_kbps, average_saturation_pct)) | ||||||
					Loading…
					
					
				
		Reference in new issue