sent_driver/
sent.rs

1//use stm32f1::stm32f103;
2use stm32f1xx_hal::{
3    pac::{self},
4    prelude::*,
5};
6
7use crate::{SettingClock, SettingDMA};
8
9// initialise the setting registers
10pub fn init(dma_set: SettingDMA, dp: pac::Peripherals) -> stm32f1xx_hal::dma::dma1::Channels {
11    let mut rcc = dp.RCC.constrain();
12    //////////////////////////////    GPIOA CONFIG     /////////////////////////////
13    // enable GPIO B
14    let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
15    // configure PB0 as input
16    gpiob.pb0.into_floating_input(&mut gpiob.crl);
17
18    ////////////////////////////     TIMER CONFIG      /////////////////////////////
19    let timer = dp.TIM3;
20    // enable TIM3
21    let add_apbenr = unsafe { &(*stm32f1xx_hal::pac::RCC::ptr()).apb1enr };
22    add_apbenr.modify(|_, w| w.tim3en().set_bit());
23
24    //
25    timer.ccmr2_input().write(|w| w.cc3s().ti3());
26    // Capture enabled on falling edge
27    timer.ccer.write(|w| w.cc3p().set_bit().cc3e().set_bit());
28    unsafe {
29        timer.dmar.write(|w| w.dmab().bits(0x81));
30    }
31    // start timer (bit CEN)
32    timer.cr1.write(|w| w.cen().set_bit());
33    // enable DMA request
34    timer.dier.write(|w| w.cc3de().set_bit());
35
36    ////////////////////////////    DMA CONFIG     /////////////////////////////////
37    let mut dma = dp.DMA1.split(&mut rcc.ahb);
38
39    // set peripheral address + don't enable address increment after each transfer
40    dma.2.set_peripheral_address(dma_set.add_periph, false);
41    // set memory address + enable address increment after each transfer
42    dma.2.set_memory_address(dma_set.add_mem, true);
43    // set how many data must be transfered
44    dma.2.set_transfer_length(dma_set.nb_data.into()); // into() -> met en usize
45    unsafe {
46        // configure the dma transfer
47        dma.2.ch().cr.modify(|_, w| {
48            w.dir() // periph -> memory
49                .clear_bit()
50                .circ() // disable circular mode
51                .clear_bit()
52                .psize() // data size in periph = 16 bits
53                .bits(0x01)
54                .msize() // data size in mem = 16 bits
55                .bits(0x01)
56                .pl() // priority level == low
57                .low()
58        });
59    }
60    // enable interrupt when transfer complete
61    dma.2.listen(stm32f1xx_hal::dma::Event::TransferComplete);
62    // enable dma
63    dma.2.start();
64
65    dma
66}
67
68// stock the 19 memory time data in a table
69pub fn time_stock(mut tab_time: [u16; 19], dma: SettingDMA) -> [u16; 19] {
70    for i in 0..19 {
71        unsafe {
72            tab_time[(i as usize)] = *((dma.add_mem + (i * 0x02) as u32) as *mut u16);
73        }
74    }
75    tab_time
76}
77
78// check if the function diff_calcul returns a result corresponding to the 56 ticks of the synchro data
79pub fn synchro(tab_time: [u16; 19], mut ind: usize, status_trame: &mut bool) -> usize {
80    let mut diff = 0;
81
82    while !(1350..=1360).contains(&diff) {
83        if ind < 11 {
84            // after ind = 11, it's not possible to have a fair frame
85            ind += 1;
86            diff = diff_calcul(tab_time[ind - 1], tab_time[ind]);
87        } else {
88            *status_trame = false; // ind >= 11 = frame false
89            break;
90        }
91    }
92
93    ind
94}
95
96// calculate the difference between time n (x) and time n+1 (y)
97// TIM3 is a auto-reload timer so we need to check if between time n and time n+1 there was a reload
98pub fn diff_calcul(x: u16, y: u16) -> u16 {
99    if x > y {
100        // if x > y => reload  65535 = timer_value_max : TIM3 (16bits)
101        65535 - x + y
102    } else {
103        y - x
104    }
105}
106
107// convert times into data ( 0 - 15)
108pub fn convert_data(
109    timer: SettingClock,
110    tab_time: [u16; 19],
111    mut ind: usize,
112    status_trame: &mut bool,
113) -> [u8; 8] {
114    let mut tab_value: [u8; 8] = [0; 8];
115    for k in 0..8 {
116        let data = (diff_calcul(tab_time[ind], tab_time[ind + 1]) as f32 * timer.period) as u8;
117        if !(36..=81).contains(&data) {
118            // data can take the next value : 36, 39, 42,..., 78, 81 = corresponding to time in us
119            *status_trame = false;
120        } else {
121            tab_value[k] = (data - 36) / 3; // return the value
122            ind += 1;
123        }
124    }
125    tab_value
126}
127
128// verify the crc received by calculate a new crc with data received
129pub fn check(tab_value: [u8; 8]) -> bool {
130    let mut checksum: u8 = 5;
131    let crclookup: [u8; 16] = [0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5];
132
133    for a in tab_value.iter().take(7).skip(1) {
134        // calculate new crc by using only the data (6 -> tab_value[1] to tab_value[6])
135
136        checksum = crclookup[(checksum as usize)];
137        checksum ^= a;
138    }
139    checksum = crclookup[(checksum as usize)];
140
141    tab_value[7] == checksum
142}
143
144// stop dma and clear the flag tcif
145pub fn stop_dma(mut dma: stm32f1xx_hal::dma::dma1::Channels) -> stm32f1xx_hal::dma::dma1::Channels {
146    let add_ifcr = unsafe { &(*stm32f1xx_hal::pac::DMA1::ptr()).ifcr };
147    add_ifcr.write(|w| w.cgif2().set_bit()); // clear the flag tcif for channel 2
148    dma.2.stop();
149    dma
150}
151
152// start dma with sttings : tcie enable and nb_data to transfert
153pub fn start_dma(
154    dma_set: SettingDMA,
155    mut dma: stm32f1xx_hal::dma::dma1::Channels,
156) -> stm32f1xx_hal::dma::dma1::Channels {
157    dma.2.set_transfer_length(dma_set.nb_data.into());
158    dma.2.listen(stm32f1xx_hal::dma::Event::TransferComplete);
159    dma.2.start();
160
161    dma
162}