diff --git a/src/libboard_artiq/src/cxp_downconn.rs b/src/libboard_artiq/src/cxp_downconn.rs new file mode 100644 index 0000000..8f07a65 --- /dev/null +++ b/src/libboard_artiq/src/cxp_downconn.rs @@ -0,0 +1,89 @@ +use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs; +use libboard_zynq::{println, timer::GlobalTimer}; +use log::info; + +use crate::{cxp_phys, pl::csr::CXP}; + +pub fn loopback_testing(channel: usize, timer: &mut GlobalTimer, speed: cxp_phys::CXP_SPEED) { + println!("=============================================================================="); + cxp_phys::change_linerate(speed); + + unsafe { + info!("waiting for tx&rx setup..."); + timer.delay_us(50_000); + // info!( + // "tx_phaligndone = {} | rx_phaligndone = {}", + // (CXP[channel].rx_txinit_phaligndone_read)(), + // (CXP[channel].rx_rxinit_phaligndone_read)(), + // ); + + // enable txdata tranmission thought MGTXTXP, required by PMA loopback + // (CXP[channel].rx_txenable_write)(1); + + info!("waiting for rx to align..."); + while (CXP[channel].rx_ready_read)() != 1 {} + info!("rx ready!"); + + // cxp_proto::rx_send_test_packet(channel); + + // FIXME: why test + trig ack doesn't work well for rx?? + // cxp_proto::rx_debug_send_trig_ack(channel); + + // const DATA_MAXSIZE: usize = 253; + // let data_size = 4; // no. of bytes + + // let data: u32 = 0xDADA as u32; + // let mut data_slice: [u8; DATA_MAXSIZE] = [0; DATA_MAXSIZE]; + // data_slice[..4].clone_from_slice(&data.to_be_bytes()); + // cxp_proto::rx_debug_send( + // channel, + // &cxp_proto::UpConnPacket::Event { + // conn_id: 0x1234_5678_u32, + // packet_tag: 0x69_u8, + // length: data_size + 3, + // event_size: data_size, + // namespace: 0x02_u8, + // event_id: 0x00_6969u16, + // timestamp: 0x1234_5678u64, + // data: data_slice, + // }, + // ) + // .expect("loopback gtx tx error"); + + // timer.delay_us(1000); // wait packet has arrive at RX async fifo + + // if (CXP[channel].rx_trigger_ack_read)() == 1 { + // (CXP[channel].rx_trigger_ack_write)(1); + // info!("trig ack and cleared"); + // } + + // if (CXP[channel].rx_bootstrap_decoder_err_read)() == 1 { + // info!("!!!!!!!DECODER ERROR!!!!!!! and cleared"); + // (CXP[channel].rx_bootstrap_decoder_err_write)(1); + // } + + // info!("packet type = {:#06X}", (CXP[channel].rx_packet_type_read)()); + + // // cxp_proto::receive(channel as u8).expect("loopback gtx rx error"); + // // cxp_proto::rx_debug_mem_print(channel); + + // // DEBUG: print loopback packets + // const LEN: usize = 20; + // let mut pak_arr: [u32; LEN] = [0; LEN]; + // let mut k_arr: [u8; LEN] = [0; LEN]; + // let mut i: usize = 0; + // while (CXP[channel].rx_debug_out_dout_valid_read)() == 1 { + // pak_arr[i] = (CXP[channel].rx_debug_out_dout_pak_read)(); + // k_arr[i] = (CXP[channel].rx_debug_out_kout_pak_read)(); + // // println!("received {:#04X}", pak_arr[i]); + // (CXP[channel].rx_debug_out_inc_write)(1); + // i += 1; + // if i == LEN { + // break; + // } + // } + + // info!("rx ready = {}", (CXP[channel].rx_rx_ready_read)()); + // // cxp_proto::print_packetu32(&pak_arr, &k_arr); + } +} diff --git a/src/libboard_artiq/src/cxp_upconn.rs b/src/libboard_artiq/src/cxp_upconn.rs new file mode 100644 index 0000000..17b928f --- /dev/null +++ b/src/libboard_artiq/src/cxp_upconn.rs @@ -0,0 +1,91 @@ +use core::slice; + +use embedded_hal::blocking::delay::DelayUs; +use io::Cursor; +use libboard_zynq::{println, timer::GlobalTimer}; + +use crate::{cxp_proto, + mem::mem::CXP_MEM, + pl::csr::{self, CXP}}; +const BUF_LEN: usize = 0x800; + +pub fn tx_test(channel: u8, timer: &mut GlobalTimer) { + const LEN: usize = 4 * 100; + let mut pak_arr: [u8; LEN] = [0; LEN]; + + let channel = channel as usize; + unsafe { + // (CXP[channel].tx_trig_delay_write)(0x86); + // (CXP[channel].tx_linktrigger_write)(0x00); + + // DEBUG: prepare the packet before tx enable to avoid overhead + preload_tx_packet( + channel as u8, + &cxp_proto::TXPacket::CtrlRead { + tag: None, + addr: 0, + length: 4, + }, + ); + + csr::cxp_phys::tx_enable_write(1); + timer.delay_us(1); + + // DEBUG: send ctrl packet or test + (CXP[channel].tx_writer_stb_write)(1); + (CXP[channel].tx_writer_stb_testseq_write)(1); + + // DEBUG: Trigger packet (NOTE: disconnected in Gateware) + // (CXP[channel].upconn_trig_stb_write)(1); // send trig + + // DEBUG: Trigger ACK packet + // (CXP[channel].upconn_ack_write)(1); + + timer.delay_us(2000); + csr::cxp_phys::tx_enable_write(0); + + // Collect data + let mut i: usize = 0; + // match channel { + // 0 => { + // while csr::cxp_phys::tx_tx0_debug_buf_dout_valid_read() == 1 { + // pak_arr[i] = csr::cxp_phys::tx_tx0_debug_buf_dout_pak_read(); + // csr::cxp_phys::tx_tx0_debug_buf_inc_write(1); + // i += 1; + // if i == LEN { + // break; + // } + // } + // } + // 1 => { + // while csr::cxp_phys::tx_tx1_debug_buf_dout_valid_read() == 1 { + // pak_arr[i] = csr::cxp_phys::tx_tx1_debug_buf_dout_pak_read(); + // csr::cxp_phys::tx_tx1_debug_buf_inc_write(1); + // i += 1; + // if i == LEN { + // break; + // } + // } + // } + // _ => {} + // } + + cxp_proto::print_packet(&pak_arr); + } +} + +fn preload_tx_packet(channel: u8, packet: &cxp_proto::TXPacket) { + let channel = channel as usize; + unsafe { + while (CXP[channel].tx_writer_busy_read)() == 1 {} + let ptr = CXP_MEM[channel].base as *mut u32; + let mut writer = Cursor::new(slice::from_raw_parts_mut(ptr as *mut u8, BUF_LEN)); + + packet.write_to(&mut writer).expect("unstable to write to tx mem"); + // DEBUG: + println!("TX MEM after writing"); + cxp_proto::print_packet(&writer.get_ref()[0..40]); + + (CXP[channel].tx_writer_word_len_write)(writer.position() as u16 / 4); + } +}