Hello,
i am building a device to "sniff" on a spi-buss (1MHz Clk) and give out the data via usb-serial out.
the spi is not standard, so as a hardware guy i use some cd4094 (shiftregisters) to have it in parallel
for the teensy-ports.
the device get selected with CS going HI on PORTE6 (INT6), generating a IRQ,
reading the Portpins connected to the cd4094 and saving it.
the main loop giving the data out via usb.
timer0 is configured as CTC, externaly clocked by the SPI Clk on the D7 Pin and toggles the output B7 after 15 pulses...
So far the thing works, but so every ca half second it giltches, somehow the ISR of INT6_vect
gets delayd and the device get selected to late, missing some data....
on the attached logic-analyser/DSO the delay is visible..
when i power the teeny from a USB 5V PSU that doesent happen, so probably the USB ISR generates this latency.
is there a possibility to reduce this latency, or define the USB ISR as NONBLOCKING, resp. to switch on the irq
in the ISR without negative consequences ?
running on win7 Arduino 1.8.5 with the teensyduino extention
many thanks for any help!
styro
here the code, very ugly
i am building a device to "sniff" on a spi-buss (1MHz Clk) and give out the data via usb-serial out.
the spi is not standard, so as a hardware guy i use some cd4094 (shiftregisters) to have it in parallel
for the teensy-ports.
the device get selected with CS going HI on PORTE6 (INT6), generating a IRQ,
reading the Portpins connected to the cd4094 and saving it.
the main loop giving the data out via usb.
timer0 is configured as CTC, externaly clocked by the SPI Clk on the D7 Pin and toggles the output B7 after 15 pulses...
So far the thing works, but so every ca half second it giltches, somehow the ISR of INT6_vect
gets delayd and the device get selected to late, missing some data....
on the attached logic-analyser/DSO the delay is visible..
when i power the teeny from a USB 5V PSU that doesent happen, so probably the USB ISR generates this latency.
is there a possibility to reduce this latency, or define the USB ISR as NONBLOCKING, resp. to switch on the irq
in the ISR without negative consequences ?
running on win7 Arduino 1.8.5 with the teensyduino extention
many thanks for any help!
styro
here the code, very ugly
Code:
#include <stdio.h> // for function sprintf
const byte Buffsize = 256;
volatile unsigned int Din_Value=0;
volatile unsigned int Din_Values[Buffsize];
volatile unsigned int Dout_Value=0;
volatile byte strobed = 0;
volatile byte rx_counter = 0;
volatile byte tx_counter = 0;
const int led_pin = 6; // 6 = Teensy++ 2.0
volatile byte startreceive = 0;
volatile byte tx_received = 0;
volatile unsigned int last_step = 0;
volatile int stepcounter = 0;
volatile unsigned int laststepcounter = 1;
volatile byte tray = 0;
volatile byte lasttray = 0;
volatile byte lastPORTF = 0;
volatile byte PORTFx = 99;
volatile byte CDSelected = 0;
volatile byte DoutStrobed = 0;
unsigned int lastDout_Value=0;
char MsgBuff[50]="";
char MsgBuff2[30]="";
void setup() {
Serial.begin(9600); // USB is always 12 Mbit/sec
PORTB = 0x00;
DDRB = 0x88; // PB7 OC0A Out
DDRC = 0x00;
DDRD = 0x00; // D7 External in Timer0
DDRF = 0x00;
DDRE = 0x02; // E1 -> strobe output
DDRA = 0x00;
PORTE = 0x02;
PORTA = 0xFF;
byte Strobe = 19; // INT7
byte CS_Bit2 = 18; // INT6
// attachInterrupt(Strobe, Strobe_interrupt, RISING);
// attachInterrupt(CS_Bit2, CS_interrupt, RISING);
Serial.println("SPI_Serial OLEOLE_TESTER 0.01et");
digitalWrite(led_pin, HIGH);
delay(500);
digitalWrite(led_pin, LOW);
EICRB = 0xF0; // rising interrupt INT7-> Strobe von Controller INT6-> Adresse Mux
EIMSK = 0xC0; // interrupts scharf
TCCR0A = 0x42; // toggle PB7 CTC mode
OCR0A = 15;
TIMSK0 = 0x02; //interrupt OCA
}
void loop() {
int rd, wr, n;
if (strobed > 0){
// PORTD ^= 0x40;
if (lastPORTF != PORTFx){
Serial.print("Strobs");
Serial.print(strobed,DEC);
Serial.print("IN:_");
Serial.print(PORTFx,HEX);
Serial.print("-");
Serial.println(PORTFx,BIN);
}
lastPORTF = PORTFx;
strobed = 0;
}
if (DoutStrobed > 0){
// PORTD ^= 0x40;
if (lastDout_Value != Dout_Value){
int2bin(MsgBuff2, Dout_Value);
sprintf(MsgBuff,"DoutStrobs %d Out %4X %s",DoutStrobed,Dout_Value,MsgBuff2);
Serial.println(MsgBuff);
}
lastDout_Value = Dout_Value;
DoutStrobed = 0;
}
if (((PINA & 0x80) != 0) && ((PINA & 0x40) == 0)&& ((PINA & 0x20) == 0)){
}else{
if (CDSelected == 1){
PORTB &= ~0x08;
CDSelected = 0;
TCCR0B = 0x00; // timer off
}
}
if (laststepcounter != stepcounter){
// Serial.print("STEP");
// Serial.println(stepcounter,DEC);
laststepcounter = stepcounter;
}
if (lasttray == 0 && tray > 0){
Serial.print("CD ");
Serial.println(((stepcounter - 9)/4) *tray ,DEC);
}
lasttray = tray;
}
char *int2bin(char *buff, unsigned int val){
byte off=0;
for (byte i=0; i <16; i++){
buff[i+off] = (val & (0x8000>>i))>0?'1':'0';
if ((i>0) && (((i+1)%4) == 0)){
off++;
buff[i+off]='\'';
}
}
buff[15+off]= 0;
return buff;
}
ISR(INT6_vect ) // CS Device Select
{
if (((PINA & 0x80) != 0) && ((PINA & 0x40) == 0)&& ((PINA & 0x20) == 0)){
if (CDSelected == 0){
TCNT0= 0;
TCCR0B = 0x07; // timer on external in
PORTB |= 0x08;
CDSelected = 1;
}
}
}
ISR(INT7_vect ) // SPI Strobe
{
sei();
Din_Value = PINC | (PINF <<8);
PORTFx = PINF;
strobed++;
rx_counter = 0;
tx_counter = 0;
TCNT0= 0;
if (last_step != (Din_Value & 0x0010)){
if (((Din_Value & 0x0040)>>2) != (Din_Value & 0x0010)){
stepcounter++;
}else{
stepcounter--;
}
if (stepcounter < 0){
stepcounter = 0;
}
last_step = (Din_Value & 0x0010);
}
if (((Din_Value & 0x0008)>>1) != (Din_Value & 0x0004)){
tray = 2;
}else if (((Din_Value & 0x0002)>>1) != (Din_Value & 0x0001)){
tray = 1;
}else{
tray = 0;
}
// PORTD &= ~0x40;
}
ISR(TIMER0_COMPA_vect ) // Timer0 OCA, generate strobe for shiftregisters
{
PORTE |= 0x02;
PORTE |= 0x02;
PORTE |= 0x02;
PORTE |= 0x02;
TCCR0B |= 0x80; // force OCA
TCCR0B = 0x00; // timer off
Dout_Value = ((PINE&0x01) << 15)|((PIND&0x7F) << 8) | ((PINB & 0x70)>>4);
DoutStrobed++;
PORTB &= ~0x08;
PORTE &= ~0x02;
}