Skip to content

Commit

Permalink
Merge pull request #122 from commaai/gmbitbang
Browse files Browse the repository at this point in the history
Gmbitbang
  • Loading branch information
geohot authored Jun 11, 2018
2 parents 875c2bd + 7edc88e commit be46c7a
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 2 deletions.
11 changes: 9 additions & 2 deletions board/drivers/can.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,21 @@ void CAN3_SCE_IRQHandler() { can_sce(CAN3); }

#endif

#include "canbitbang.h"

void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
if (safety_tx_hook(to_push) && !can_autobaud_enabled[bus_number]) {
if (bus_number < BUS_MAX) {
// add CAN packet to send queue
// bus number isn't passed through
to_push->RDTR &= 0xF;
can_push(can_queues[bus_number], to_push);
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
if (bus_number == 3 && can_num_lookup[3] == 0xFF) {
// TODO: why uint8 bro? only int8?
bitbang_gmlan(to_push);
} else {
can_push(can_queues[bus_number], to_push);
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
}
}
}
}
Expand Down
156 changes: 156 additions & 0 deletions board/drivers/canbitbang.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#define MAX_BITS_CAN_PACKET (64+44+25)

// returns out_len
int do_bitstuff(char *out, char *in, int in_len) {
int last_bit = -1;
int bit_cnt = 0;
int j = 0;
for (int i = 0; i < in_len; i++) {
char bit = in[i];
out[j++] = bit;

// do the stuffing
if (bit == last_bit) {
bit_cnt++;
if (bit_cnt == 5) {
// 5 in a row the same, do stuff
last_bit = !bit;
out[j++] = last_bit;
bit_cnt = 1;
}
} else {
// this is a new bit
last_bit = bit;
bit_cnt = 1;
}
}
return j;
}

int append_crc(char *in, int in_len) {
int crc = 0;
for (int i = 0; i < in_len; i++) {
crc <<= 1;
if (in[i] ^ ((crc>>15)&1)) {
crc = crc ^ 0x4599;
}
crc &= 0x7fff;
}
for (int i = 14; i >= 0; i--) {
in[in_len++] = (crc>>i)&1;
}
return in_len;
}

int append_bits(char *in, int in_len, char *app, int app_len) {
for (int i = 0; i < app_len; i++) {
in[in_len++] = app[i];
}
return in_len;
}

int append_int(char *in, int in_len, int val, int val_len) {
for (int i = val_len-1; i >= 0; i--) {
in[in_len++] = (val&(1<<i)) != 0;
}
return in_len;
}

int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
char pkt[MAX_BITS_CAN_PACKET];
char footer[] = {
1, // CRC delimiter
1, // ACK
1, // ACK delimiter
1,1,1,1,1,1,1, // EOF
1,1,1, // IFS
};
#define SPEEED 30

int len = 0;

// test packet
int dlc_len = to_bang->RDTR & 0xF;
len = append_int(pkt, len, 0, 1); // Start-of-frame
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
len = append_int(pkt, len, 0, 3); // RTR+IDE+reserved
len = append_int(pkt, len, dlc_len, 4); // Data length code

// append data
for (int i = 0; i < dlc_len; i++) {
unsigned char dat = ((unsigned char *)(&(to_bang->RDLR)))[i];
len = append_int(pkt, len, dat, 8);
}

// append crc
len = append_crc(pkt, len);

// do bitstuffing
len = do_bitstuff(out, pkt, len);

// append footer
len = append_bits(out, len, footer, sizeof(footer));
return len;
}

// hardware stuff below this line

#ifdef PANDA

void set_bitbanged_gmlan(int val) {
if (val) {
GPIOB->ODR |= (1 << 13);
} else {
GPIOB->ODR &= ~(1 << 13);
}
}

void bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) {
puts("called bitbang_gmlan\n");

char pkt_stuffed[MAX_BITS_CAN_PACKET];
int len = get_bit_message(pkt_stuffed, to_bang);

// actual bitbang loop
set_bitbanged_gmlan(1); // recessive
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
enter_critical_section();

// wait for bus silent for 7 frames
int silent_count = 0;
while (silent_count < 7) {
int read = get_gpio_input(GPIOB, 12);
silent_count++;
if (read == 0) {
silent_count = 0;
}
int lwait = TIM2->CNT;
while (get_ts_elapsed(TIM2->CNT, lwait) < SPEEED);
}

// send my message with optional failure
int last = 1;
int init = TIM2->CNT;
for (int i = 0; i < len; i++) {
while (get_ts_elapsed(TIM2->CNT, init) < (SPEEED*i));
int read = get_gpio_input(GPIOB, 12);
if ((read == 0 && last == 1) && i != (len-11)) {
puts("ERR: bus driven at ");
puth(i);
puts("\n");
goto fail;
}
set_bitbanged_gmlan(pkt_stuffed[i]);
last = pkt_stuffed[i];
}

fail:
set_bitbanged_gmlan(1); // recessive
exit_critical_section();
set_gpio_mode(GPIOB, 13, MODE_INPUT);

puts("bitbang done\n");
}

#endif

35 changes: 35 additions & 0 deletions tests/gmbitbang/rigol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python
import numpy as np
import visa
import matplotlib.pyplot as plt

resources = visa.ResourceManager()
print resources.list_resources()

scope = resources.open_resource('USB0::0x1AB1::0x04CE::DS1ZA184652242::INSTR', timeout=2000, chunk_size=1024000)
print(scope.query('*IDN?').strip())

#voltscale = scope.ask_for_values(':CHAN1:SCAL?')[0]
#voltoffset = scope.ask_for_values(":CHAN1:OFFS?")[0]

#scope.write(":STOP")
scope.write(":WAV:POIN:MODE RAW")
scope.write(":WAV:DATA? CHAN1")[10:]
rawdata = scope.read_raw()
data = np.frombuffer(rawdata, 'B')
print data.shape

s1 = data[0:650]
s2 = data[650:]
s1i = np.argmax(s1 > 100)
s2i = np.argmax(s2 > 100)
s1 = s1[s1i:]
s2 = s2[s2i:]

plt.plot(s1)
plt.plot(s2)
plt.show()
#data = (data - 130.0 - voltoffset/voltscale*25) / 25 * voltscale

print data

28 changes: 28 additions & 0 deletions tests/gmbitbang/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env python
import time
from panda import Panda

p1 = Panda('430026000951363338383037')
p2 = Panda('380016000551363338383037')

# this is a test, no safety
p1.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
p2.set_safety_mode(Panda.SAFETY_ALLOUTPUT)

# get versions
print(p1.get_version())
print(p2.get_version())

# this sets bus 2 to actually be GMLAN
p2.set_gmlan(bus=2)

# send w bitbang then without
while 1:
p1.set_gmlan(bus=None)
p1.can_send(123, "\x01\x02\x03\x04\x05\x06\x07\x08", bus=3)
p1.set_gmlan(bus=2)
p1.can_send(123, "\x01\x02\x03\x04\x05\x06\x07\x08", bus=3)
time.sleep(0.01)
print p2.can_recv()
exit(0)

32 changes: 32 additions & 0 deletions tests/gmbitbang/test_packer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <stdint.h>

typedef struct {
uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */
uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */
uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */
uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */
} CAN_FIFOMailBox_TypeDef;

#include "../../board/drivers/canbitbang.h"

int main() {
char out[300];
CAN_FIFOMailBox_TypeDef to_bang = {0};
to_bang.RIR = 20 << 21;
to_bang.RDTR = 1;
to_bang.RDLR = 1;

int len = get_bit_message(out, &to_bang);
printf("T:");
for (int i = 0; i < len; i++) {
printf("%d", out[i]);
}
printf("\n");
printf("R:0000010010100000100010000010011110111010100111111111111111");
printf("\n");
return 0;
}



0 comments on commit be46c7a

Please sign in to comment.