Quelltext /~heha/mb-iwp/Antriebe/Linak-Servo/hips-210406.zip/hips.h

#pragma once
#include <stm32f10x.h>
#include "usb.h"

/* Hardware:
A3	T2C4	PWM-Ausgang, steuert die Bremskraft
A4		frei
A5	SCK1	Messschieber-Takt vom LM393 ¹
A6	(ADC6)	Verdreh-Sensor (Mikrotaster) ¹
A7	MOSI1	Messschieber-Daten vom LM393 ¹
(A11		USB D-)
(A12		USB D+)
B0	ADC8	Kraftmessdose, ≥ 100 kSa/s
B1	ADC9	Potenziometer
B10	TxD3	Interface der Linak-Steuerung
B11	RxD3	Interface der Linak-Steuerung
(B12		Blaue LED, low-aktiv)
¹ erfordert chip-internen Pullup

Verwendung der Peripherie:
ADC1	Kraftmessdose (schnell und kontinuierlich)
ADC2	Potenziometer (gelegentlich)
USART3	Linak-Servo
SPI1	Messschieber
Timer2	PWM-Ausgang
Timer3	Triggerverzögerung für ADC1
Timer4	Endeerkennung für SPI1
DMA1CH1	ADC1 (Kraftmessdose)
DMA1CH2	SPI1 (Messschieber)
USB	HID+WebUSB
*/

void delay(uint32_t);
void set_sysclock();
void revert_sysclock();
void idle();

// Alle Reports verwenden eine Report-ID.
// Konstruktoren vermeiden für Zusammenfassung in Union
struct Report{
 byte repid;
 operator byte*() {return &repid;}	// Als Ganzes ansprechen
};

extern struct RepF:public Report{
 byte flags;	// Bit 0 = Benutze folgende Bremskraftvorgabe
 int16_t brems;	// Bremskraftvorgabe, 0..4095
 int16_t k1,k2;	// Triggerschwellen für Kraftstoß-Oszillogramm-Report, 0..4095
 int16_t tp,tg;	// Prätrigger, Gesamtzeit (in Samples)
 static constexpr int16_t tg_max=500;
}repF;

struct Simplestat{	// size: 8 (ohne Quadratsumme)
 int16_t min,max;
 int32_t sum;
// int64_t qsum;
 void add(int16_t val) {
  if (min>val) min=val;
  if (max<val) max=val;
  sum+=val;
//  qsum+=(int32_t)val*val;	// Wie teuer ist diese Multiplikation?
 }
 void reset() {min=32767; max=-32767;sum=0;/*qsum=0;*/}
};

namespace adc{
 void init();
 void reloadFeature(byte);	// bei Änderung von repF: Triggerschwellen nachführen
 void arm();
 void manualtrigger();
 unsigned collect(int16_t*,unsigned);
 uint16_t get_poti(Simplestat&);	// liefert min, max, Mittelwert
// uint32_t getTriggerState();
}

extern struct RepI:public Report{	// size: 22
 byte flags;	// Bits:
		// 7 = Dirty (bei Interrupt-In stets 1, bei Abfrage via Control-Pipe je nachdem) *
		// 6 = drohender Überlauf der Statistik (durch fehlenden Messschieber) *
		// 5 = ?
		// 4 = ?
		// 3:2 = Phase der Triggerung:
		//	0 = Abwarten von <repF.tp> Samples (nur wenn repF.tp>0)
		//	1 = Warten auf erste Triggerbedingung (Unterschreitung <repF.k1>)
		//	2 = Warten auf zweite Triggerbedingung (Überschreitung <repF.k2>)
		//	3 = Abwarten von <repF.tg-repF.tp> Samples
		// 1 = Neuer Wert vom Messschieber *
		// 0 = Zustand des Verdreh-Tasters
 uint16_t n;	// Anzahl Statistik-Einträge (betrifft p.sum und k.sum) *
 Simplestat p;	// Poti(×2) *
 Simplestat k;	// Kraft(×4) *
 int16_t weg;
 void reset();	// * = Dieses Bits/Werte werden nach Interrupt-Transfer gelöscht
}repI;

extern struct RepLinak:public Report{
 byte addr;	// Bit 7 = lesen
 uint16_t value;
}repLinak;

extern struct RepStoß:public Report{
 byte flags;		// Bit 7 = k1-Trigger wurde erfüllt; 6:0 = Füllung
 int16_t kraft[250];	// A/D-Werte des Kraftstoßes
 inline void reset() {flags=0; adc::arm();}	// nach Absenden des Reports: Erneut scharfmachen
 inline void collect() {
  adc::collect(kraft,elemof(kraft));
  flags=0x80|elemof(kraft);
 }	// Nach verzögertem Trigger: Daten aus DMA-Puffer einsammeln
}repStoß;

struct RepReboot:public Report{
 byte doit;	// Nur wenn 1
};

/* Simple function pointer type to call user program */
typedef void (*func_ptr_t)();

extern func_ptr_t vtbl[16+56];

namespace usb{
extern byte DevStatus;	// Bit 0: SelfPower, Bit 1: RemoteWakeup
extern byte DevConfig;
void shutdown();
void init();
// Diese Routinen können blockieren und rufen dann idle()!
// Rekursion ist zu vermeiden!
void poll();
bool send0(const byte*,unsigned);
bool send(byte,const byte*,unsigned);
// Der letzte Parameter steuert ob Short-Packets okay sind, und ist ein Zeiger
// auf die empfangenen Bytes.
// Diese Routine blockiert und ruft idle()!
bool recv(byte,byte*,unsigned,unsigned* =nullptr);
}
// Callbacks
bool onSetReport(uint16_t,uint16_t);
bool onGetReport(uint16_t,uint16_t);

#define BB_BIT(a,b) (*(volatile uint32_t*)(((uint32_t)&(a)&0xFF000000)+0x02000000+((uint32_t)&(a)&0x00FFFFFFF)*32+(b)*4))

#define LED_INIT()	BB_BIT(GPIOB->CRH,16) = 1	// output open drain
#define LED		BB_BIT(GPIOB->ODR,12)		// 0 = on, 1 = off

namespace caliper{
 void init();	// SPI1 und DMA1CH2 aktivieren
}

namespace pwm{
 void init();
 inline void out(uint16_t v) {TIM2->CCR4=v;}
}
Vorgefundene Kodierung: UTF-80