mirror of
https://github.com/eddyem/IR-controller.git
synced 2025-12-06 10:45:15 +03:00
272 lines
8.0 KiB
C
272 lines
8.0 KiB
C
/*
|
|
* main.c
|
|
*
|
|
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "main.h"
|
|
#include "hardware_ini.h"
|
|
#include "cdcacm.h"
|
|
#include "uart.h"
|
|
#include "spi.h"
|
|
#include "stepper_motors.h"
|
|
|
|
volatile uint32_t Timer = 0, tOVRFL = 0; // global timer (milliseconds), overflow counter
|
|
usbd_device *usbd_dev;
|
|
|
|
uint8_t ADC_monitoring = 0; // ==1 to make continuous monitoring
|
|
|
|
uint32_t ad7794_on = 0;
|
|
uint32_t ad7794_values[TRD_NO];
|
|
uint8_t doubleconv = 1; // ==0 to single conversion; 1 to double (with currents reversing)
|
|
#define ADC_direct() setup_AD7794(EXTREFIN_1 | REF_DETECTION | UNIPOLAR_CODING, IEXC_DIRECT | IEXC_1MA)
|
|
#define ADC_reverse() setup_AD7794(EXTREFIN_1 | REF_DETECTION | UNIPOLAR_CODING, IEXC_SWAPPED | IEXC_1MA)
|
|
#define RESET_ADC() do{N = 0; ad7794_on = 0; step++; return; }while(0)
|
|
/**
|
|
* reads next value of voltage on TRD
|
|
* function calls from anywhere
|
|
* internal counter step counts number of operation: because of very long
|
|
* work of ADC function should be called several times to measure all
|
|
*
|
|
* @param doubleconv == 1 to do double conversion (with currents reversing)
|
|
*/
|
|
void read_next_TRD(){
|
|
static uint8_t step = 0; // step of operation
|
|
static uint8_t N = 0; // number of current device
|
|
static uint32_t val0 = 0, val1 = 0; // readed values
|
|
// "default" in switch will process last step
|
|
switch (step){ // now we should do something depending on current step value
|
|
case 0: // step 0: set address
|
|
if(N == 0 || !ad7794_on) AD7794_init(); // reset ADC in beginning of each set
|
|
//P("Step 0: read_next_TRD, N=", uart1_send);
|
|
//print_int(N, uart1_send);
|
|
//newline(uart1_send);
|
|
gpio_set(ADC_ADDR_PORT, ADC_SET_ADDR(N) | ADC_EN_PIN); // set address & enable switch
|
|
val0 = val1 = 0;
|
|
step++;
|
|
break;
|
|
case 1: // step 1: prepare reading in 1st current direction or single reading
|
|
if(!val0){ // 1st value isn't ready yet
|
|
if(!ADC_direct()){ // error: we can't setup reading
|
|
// ad7794_values[N] = 0;
|
|
RESET_ADC(); // reset steps counter to re-initialize + mark ad7794_on = 0
|
|
}
|
|
val0 = read_AD7794(0);
|
|
if(!val0) RESET_ADC();
|
|
break;
|
|
}
|
|
if(val0 == AD7794_NOTRDY){ // data not ready yet
|
|
val0 = read_AD7794(0);
|
|
if(!val0 || val0 == AD7794_NOTRDY) break; // we'll process error in next time
|
|
// All OK, prepare second reading
|
|
if(doubleconv){ // double conversion -> prepare
|
|
if(!ADC_reverse()){ // we can't setup it, but we have 1st value
|
|
//ad7794_values[N] = val0 << 1; // double val0
|
|
RESET_ADC();
|
|
}else{
|
|
val1 = read_AD7794(0); // process it later
|
|
}
|
|
}else{ // simply copy value instead of multiplying by 2
|
|
ad7794_values[N] = val0 << 1;
|
|
step++;
|
|
}
|
|
}else{ // val0 ready, check val1; we can go here only when doubleconv != 0
|
|
if(!val1){ // error: on previous step we had to get some value or AD7794_NOTRDY
|
|
//ad7794_values[N] = 0;
|
|
RESET_ADC();
|
|
}
|
|
if(val1 == AD7794_NOTRDY){ // val1 not ready yet
|
|
val1 = read_AD7794(0);
|
|
}else{ // all OK, we can put sum of val0 & val1 into array
|
|
ad7794_values[N] = val0 + val1;
|
|
step++;
|
|
}
|
|
}
|
|
break;
|
|
default: // last step - turn off multiplexer
|
|
step = 0;
|
|
gpio_clear(ADC_ADDR_PORT, ADC_ADDR_MASK | ADC_EN_PIN); // disable com & clear address bytes
|
|
N++; // and increment TRD counter
|
|
if(N == TRD_NO) N = 0;
|
|
}
|
|
}
|
|
|
|
//uint8_t curSPI = 1;
|
|
|
|
void AD7794_init(){
|
|
uint8_t i;
|
|
ad7794_on = 0;
|
|
i = reset_AD7794();
|
|
if(i != ADC_NO_ERROR){
|
|
if(i == ADC_ERR_NO_DEVICE){
|
|
// print_int(curSPI, lastsendfun);
|
|
MSG("ADC signal is absent! Check connection.\n", "[ " STR_EXTADC_INIT " ERR ]\n");
|
|
/* if(curSPI == 1){
|
|
curSPI = 2;
|
|
switch_SPI(SPI2);
|
|
}else{
|
|
curSPI = 1;
|
|
switch_SPI(SPI1);
|
|
}*/
|
|
}
|
|
}else{
|
|
if(!setup_AD7794(INTREFIN | REF_DETECTION | UNIPOLAR_CODING, IEXC_DIRECT | IEXC_1MA)
|
|
|| !AD7794_calibration(0)){
|
|
MSG("Error: can't initialize AD7794!\n", "[ " STR_EXTADC_INIT " ERR ]\n");
|
|
}else{
|
|
ad7794_on = 1;
|
|
DBG("ADC ready\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(){
|
|
//int i;
|
|
uint32_t Shtr_blink_timer = 0, Old_timer = 0, lastTRDread = 0, lastTmon = 0;
|
|
int oldusbdatalen = 0;
|
|
//SPI_read_status SPI_stat;
|
|
|
|
// RCC clocking: 8MHz oscillator -> 72MHz system
|
|
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
|
|
|
// turn off SWJ/JTAG
|
|
AFIO_MAPR = AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF;
|
|
|
|
// GPIO
|
|
GPIO_init();
|
|
|
|
usb_disconnect(); // turn off USB while initializing all
|
|
|
|
// init USART1
|
|
UART_init(USART1);
|
|
|
|
// USB
|
|
usbd_dev = USB_init();
|
|
|
|
// SysTick is a system timer with 1mc period
|
|
SysTick_init();
|
|
|
|
// instead of SPI1 we use those pins to control shutter and system state
|
|
// SPI2 used for working with external ADC
|
|
switch_SPI(SPI2); // init SPI2
|
|
SPI_init();
|
|
init_ow_dmatimer();
|
|
|
|
// wait a little and then turn on USB pullup
|
|
// for (i = 0; i < 0x800000; i++)
|
|
// __asm__("nop");
|
|
|
|
// init ADC
|
|
ADC_init();
|
|
ADC_calibrate_and_start();
|
|
|
|
steppers_init();
|
|
|
|
usb_connect(); // turn on USB
|
|
shutter_init();
|
|
|
|
read_stored_data(); // copy stored data into RAM
|
|
|
|
LED_STATUS_OK(); // All initialized - light up LED
|
|
while(1){
|
|
usbd_poll(usbd_dev);
|
|
if(oldusbdatalen != usbdatalen){ // there's something in USB buffer
|
|
usbdatalen = parce_incoming_buf(usbdatabuf, usbdatalen, usb_send);
|
|
oldusbdatalen = usbdatalen;
|
|
}
|
|
check_and_parce_UART(USART1); // also check data in UART buffers
|
|
if(ad7794_on){
|
|
if(Timer != lastTRDread){ // run this not more than once in 1ms
|
|
lastTRDread = Timer;
|
|
read_next_TRD();
|
|
}
|
|
}
|
|
OW_process(); // process 1-wire commands
|
|
if(OW_DATA_READY()){
|
|
OW_CLEAR_READY_FLAG();
|
|
#ifdef EBUG
|
|
OW_printID(0, lastsendfun);
|
|
#endif
|
|
}
|
|
process_stepper_motors(); // check flags of motors' timers
|
|
process_shutter(); // shutter state machine
|
|
|
|
if(Timer - Shtr_blink_timer > 500 || Timer < Shtr_blink_timer){
|
|
Shtr_blink_timer = Timer;
|
|
// shutter LED will be blinking until init occurs
|
|
if(Shutter_State == SHUTTER_NOTREADY)
|
|
gpio_toggle(LED_SHUTTER_PORT, LED_SHUTTER_PIN);
|
|
}
|
|
|
|
if(Timer - Old_timer > 999){ // one-second cycle
|
|
Old_timer += 1000;
|
|
// init shutter if error occurs
|
|
if(Shutter_State == SHUTTER_NOTREADY){
|
|
shutter_init();
|
|
}
|
|
//OW_fill_ID(0);
|
|
//gpio_toggle(GPIOC, GPIO12); // toggle LED
|
|
//gpio_toggle(GPIO_BANK_SPI2_MOSI, GPIO_SPI2_MOSI);
|
|
//gpio_toggle(GPIO_BANK_SPI2_SCK, GPIO_SPI2_SCK);
|
|
// if(!ad7794_on) AD7794_init(); // try to init ADC if it doesn't work
|
|
//print_int(Timer/1000, usb_send);
|
|
}else if(Timer < Old_timer){ // Timer overflow
|
|
Old_timer = 0;
|
|
tOVRFL++; // this is an overflow counter - for workinkg in long-long time interval
|
|
}
|
|
|
|
if((Timer - lastTmon > 9999) || (Timer < lastTmon)){ // run constant monitoring of ADC values each 10 seconds
|
|
lastTmon += 10000;
|
|
if(ADC_monitoring){
|
|
print_time(lastsendfun);
|
|
print_int_ad_vals(lastsendfun);
|
|
print_ad_vals(lastsendfun);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* SysTick interrupt: increment global time & send data buffer through USB
|
|
*/
|
|
void sys_tick_handler(){
|
|
Timer++;
|
|
usbd_poll(usbd_dev);
|
|
usb_send_buffer();
|
|
}
|
|
|
|
// pause function, delay in ms
|
|
void Delay(uint16_t _U_ time){
|
|
uint32_t waitto = Timer + time;
|
|
while(Timer < waitto);
|
|
}
|
|
|
|
/**
|
|
* print current time in milliseconds: 4 bytes for ovrvlow + 4 bytes for time
|
|
* with ' ' as delimeter
|
|
*/
|
|
void print_time(sendfun s){
|
|
if(mode == LINE_MODE) P("[ " STR_PRINT_TIME " ", s);
|
|
print_int(tOVRFL, s);
|
|
s(' ');
|
|
print_int(Timer, s);
|
|
if(mode == LINE_MODE) P(" ]\n", s);
|
|
else if(mode == BYTE_MODE) s(' ');
|
|
}
|