~d-nelson/research-assistant/nextDNK

« back to all changes in this revision

Viewing changes to RAPlugins/Monitor SEX/MSDN2060 Monitor SEX/MSDN2060.c

  • Committer: Dmitrii
  • Date: 2024-02-20 00:11:14 UTC
  • Revision ID: d.nelson@mail.ioffe.ru-20240220001114-gpu9jqwusp62baxm
Structural changes are in progress

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
////////////////////////////////////////////////////////////////////////////////
2
 
/*! @file MSDN2060.c  Firmware for Monitor SEX.
3
 
- Part of the MSDN firmware.
4
 
- Part of the Research Assistant project.
5
 
- Uses  LUFA library written by
6
 
   - Copyright(C) 2012, Dean Camera, dean [at] fourwalledcubicle [dot] com,
7
 
                                     www.lufa-lib.org.
8
 
 
9
 
- Copyright(C) 2024, Dmitry K. Nelson, St.Petersburg, Russia.
10
 
                     D.Nelson@mail.ioffe.ru
11
 
- Copyright(C) 2016, Viktor E. Bursian, St.Petersburg, Russia.
12
 
                     Viktor.Bursian@mail.ioffe.ru
13
 
*///////////////////////////////////////////////////////////////////////////////
14
 
#include "Microsin_USB_IO.h"
15
 
#include "CommandParser.h"
16
 
#include <avr/wdt.h>
17
 
#include <avr/power.h>
18
 
#include <inttypes.h>
19
 
#include <avr/iousb162.h>
20
 
#include <avr/interrupt.h>
21
 
#include <util/delay.h>     /* для _delay_us() */
22
 
 
23
 
#define ADC_CS PB5
24
 
#define ADC_CLK PB6
25
 
#define ADC_DO PC7
26
 
#define INT6ENABLE 0b01000000
27
 
 
28
 
/* --------------------------------------------------------------------------------
29
 
К ножке 2 MCP3201 (IN+) подключено измеряемое напряжение
30
 
Вход внешней синхронизации - Бит 6 порта D (INT6)
31
 
Сигнал CS (активный 0) - Бит 5 порта B
32
 
Сигнал CLK (действие по фронту RISE) - Бит 6 порта B
33
 
Считывание данных - Бит 7 порта C
34
 
----------------------------------------------------------------------------------*/
35
 
 
36
 
uint16_t PointsNum = 100;  // количество точек в кадре
37
 
uint16_t PointNo = 0;  // номер регистрируемой точки
38
 
uint8_t PeriodInTicks = 10;     // Число тиков (по 16 мкс) на период измерения
39
 
uint16_t DelayInTicks =100;  // Число тиков (по 1/2 мкс) на задержку
40
 
uint16_t AdcResult; // 12 бит
41
 
bool GetADC = false;
42
 
 
43
 
void ReadMCP3201ADC ()
44
 
{
45
 
  uint8_t i;
46
 
 
47
 
  // начальное состояние у CLK 0, у CS 1.
48
 
  PORTB |= ((1<<ADC_CS)|(0<<ADC_CLK));
49
 
 
50
 
  //ADC_CS=0 активируем выборку чипа
51
 
  PORTB &= ~(1<<ADC_CS);
52
 
  _delay_us(1.0); // задержка 1 мкс
53
 
 
54
 
  ////////////////////////////////////////////////////
55
 
  // передаем 3 такта инициализации
56
 
  for(i=0; i< 3;i++)
57
 
  {
58
 
    PORTB |= (1<<ADC_CLK); //ADC_CLK=1
59
 
    _delay_us(1.0); // задержка около 2 мкс
60
 
    PORTB &= ~(1<<ADC_CLK);//ADC_CLK=0
61
 
  }
62
 
  _delay_us(1.0); // задержка 1 мкс
63
 
 
64
 
  ////////////////////////////////////////////////////
65
 
  // чтение 12 бит результата ADC, старший бит первый
66
 
  AdcResult=0;
67
 
  for(i=0;i<12;i++)
68
 
  {
69
 
    PORTB |= (1<<ADC_CLK); //ADC_CLK=1
70
 
    _delay_us(1.0); // задержка 1 мкс
71
 
    AdcResult<<=1;
72
 
    if (PINC & (1<<ADC_DO))
73
 
    AdcResult |= 1;
74
 
    PORTB &= ~(1<<ADC_CLK);//ADC_CLK=0
75
 
    _delay_us(1.0); // задержка 1 мкс
76
 
  }
77
 
  PORTB |= ((1<<ADC_CS)|(0<<ADC_CLK));
78
 
}
79
 
 
80
 
void StartDelay(void)
81
 
{
82
 
  TCNT1H = 0x00;                        // Обнуляем
83
 
  TCNT1L = 0x00;                        // счетчик
84
 
  TIFR0 |= (1 << OCF0A);    // Сбрасываем прерывания таймера TIMER0
85
 
  TIFR1 |= (1 << OCF1A);    // Сбрасываем прерывания таймера TIMER1
86
 
  TIMSK0 &= ~(1 << OCIE0A);     // Запрещаем прерывания по таймеру TIMER0
87
 
  TIMSK1 |= (1 << OCIE1A);      // Разрешаем прерывания по таймеру TIMER1
88
 
}
89
 
 
90
 
int8_t  ExecuteCommand0 (const char  command)
91
 
{
92
 
  switch( command ){
93
 
    case 'S':
94
 
      EIFR |= INT6ENABLE;   // Забыть про необработанные сигналы прерывания,
95
 
                            // случившиеся пока оно было запрещено.
96
 
      EIMSK |= INT6ENABLE;      // Разрешаем внешнее прерывание
97
 
      break;
98
 
    case 'X':
99
 
      EIMSK &= ~INT6ENABLE;               // Запрещаем внешнее прерывание
100
 
      TIMSK0 &= ~(1 << OCIE0A); // Запрещаем прерывания по таймеру TIMER0
101
 
      TIMSK1 &= ~(1 << OCIE1A); // Запрещаем прерывания по таймеру TIMER1
102
 
      break;
103
 
    default:
104
 
        return 1;
105
 
  }
106
 
  return 0;
107
 
}
108
 
 
109
 
int8_t  ExecuteCommand2 (const char     command
110
 
                        ,const uint8_t  argument)
111
 
{
112
 
  switch( command ){
113
 
    case 'T':{
114
 
      PeriodInTicks = argument;  // период измерения в тиках по 16 мкс
115
 
      OCR0A = PeriodInTicks;    // Заносим количество тактов в регистр счетчика
116
 
      break;
117
 
    }
118
 
    default:
119
 
      return 1;
120
 
  }
121
 
  return 0;
122
 
}
123
 
 
124
 
int8_t  ExecuteCommand4 (const char      command
125
 
                        ,const uint16_t  argument)
126
 
{
127
 
  switch( command ){
128
 
    case 'D':{
129
 
      DelayInTicks = argument; // задержка начала измерения в тиках по 1/2 мкс
130
 
      OCR1AH = (uint8_t)((DelayInTicks >> 8) & 0xFF);   // Заносим количество тактов
131
 
      OCR1AL = (uint8_t)(DelayInTicks & 0xFF);                  // в регистр счетчика
132
 
      break;
133
 
    }
134
 
  case 'N':{
135
 
    PointsNum = argument; // количество точек в кадре
136
 
    break;
137
 
  }
138
 
    default:
139
 
      return 1;
140
 
  }
141
 
  return 0;
142
 
}
143
 
 
144
 
int8_t  ExecuteCommand8 (const char      command
145
 
                        ,const uint32_t  argument)
146
 
{
147
 
  return 1;
148
 
}
149
 
 
150
 
 
151
 
 
152
 
void  SetupHardware (void)
153
 
{
154
 
  /* Disable watchdog if enabled by bootloader/fuses */
155
 
  MCUSR &= ~(1 << WDRF);
156
 
  wdt_disable();
157
 
 
158
 
  /* Disable clock division */
159
 
  clock_prescale_set(clock_div_1);
160
 
  // Установки таймеров --------------------------------
161
 
 
162
 
  TCCR0A = (0 << COM0A1) |      //  Инициализация таймера микроконтроллера TIMER0
163
 
           (0 << COM0A0) |
164
 
           (0 << COM0B1) |
165
 
           (0 << COM0B0) |
166
 
           (1 << WGM01) |       // Режим сброса при совпадении OCR0A
167
 
           (0 << WGM00);
168
 
 
169
 
  TCCR0B = (0 << FOC0A) |
170
 
           (0 << FOC0B) |
171
 
           (0 << WGM02) |
172
 
           (0 << CS12) |    // Выбор тактовой частоты
173
 
           (1 << CS11) |    // Данными битами
174
 
           (1 << CS10);     // установлена частота с делением на 64 (время на такт 16 мкс)
175
 
 
176
 
  OCR0A = 0;    // Заносим количество тактов в регистр счетчика
177
 
  TIMSK0 &= ~(1 << OCIE0A);     // Запрещаем прерывания по таймеру TIMER0
178
 
 
179
 
  TCCR1A = (0 << COM1A1) |      //  Инициализация таймера микроконтроллера TIMER1
180
 
           (0 << COM1A0) |
181
 
           (0 << COM1B1) |
182
 
           (0 << COM1B0) |
183
 
           (0 << FOC1A) |
184
 
           (0 << FOC1B) |
185
 
           (0 << WGM11) |
186
 
           (0 << WGM10);
187
 
 
188
 
 
189
 
  TCCR1B = (0 << ICNC1) |
190
 
           (0 << ICES1) |
191
 
           (0 << WGM13) |
192
 
           (1 << WGM12) |   // Режим сброса при совпадении OCR1A
193
 
           (0 << CS12) |    // Выбор тактовой частоты
194
 
           (1 << CS11) |    // Данными битами
195
 
           (0 << CS10);     // установлена частота с делением на 8 (время на такт 1/2 мкс)
196
 
  PeriodInTicks = 0;
197
 
  OCR1AH = (uint8_t)((PeriodInTicks >> 8) & 0xFF);      // Заносим количество тактов
198
 
  OCR1AL = (uint8_t)(PeriodInTicks & 0xFF);                     // в регистр счетчика
199
 
  TIMSK1 &= ~(1 << OCIE1A);                                     // Запрещаем прерывания по таймеру TIMER1
200
 
  // -----------------------------------------------------------------------------
201
 
 
202
 
  // Установки для внешнего прерывания INT6 (бит 6 порта D) --------------------
203
 
  EICRB = 0b00110000;   // interrupt PCINT1 on rising edge
204
 
  EIMSK &= ~INT6ENABLE;         // Запрет прерывания
205
 
 
206
 
  //настройка входа считывания данных АЦП как входа без pullup
207
 
  DDRC &= ~(1<<ADC_DO);
208
 
  PORTC &= ~(1<<ADC_DO);
209
 
  //настройка выходов, у CLK начальное состояние 0,
210
 
  // у CS начальное состояние 1.
211
 
  DDRB |= ((1<<ADC_CS)|(1<<ADC_CLK));
212
 
  PORTB |= ((1<<ADC_CS)|(0<<ADC_CLK));
213
 
}
214
 
 
215
 
 
216
 
void  BeforeLoop (void)
217
 
{
218
 
}
219
 
 
220
 
 
221
 
void  InLoop (void)
222
 
{
223
 
  if (GetADC) {
224
 
    GetADC = false;
225
 
    ReadMCP3201ADC ();
226
 
    SendNumberToUSB(PointNo);
227
 
    SendCharToUSB ('P');
228
 
    SendNumberToUSB(AdcResult);
229
 
    Send_EOL_ToUSB ();
230
 
    if (PointNo >= PointsNum) {
231
 
      TIMSK0 &= ~(1 << OCIE0A); // Запрещаем прерывания по таймеру TIMER0
232
 
//  Здесь можно вставить сообщение конца кадра
233
 
    };
234
 
  };
235
 
 
236
 
}
237
 
 
238
 
//-----------------------------------------------------------------------------
239
 
// Обработчик прерывания от таймера 1 (COMPA)
240
 
//-----------------------------------------------------------------------------
241
 
ISR(TIMER1_COMPA_vect){
242
 
  sei();                      // Дадим возможность обработать прерывания от USB...
243
 
  TIMSK1 &= ~(1 << OCIE1A);       // Запрещаем прерывания по таймеру TIMER1
244
 
  EIMSK &= ~INT6ENABLE;             // Запрещаем внешнее прерывание
245
 
  TCNT0 = 0x00;               // Обнуляем счетчик таймера TIMER0
246
 
  TIMSK0 |= (1 << OCIE0A);    // Разрешаем прерывания по таймеру TIMER0
247
 
  PointNo = 1;
248
 
  GetADC = true;
249
 
}
250
 
 
251
 
//-----------------------------------------------------------------------------
252
 
// Обработчик прерывания от таймера 0 (COMPA)
253
 
//-----------------------------------------------------------------------------
254
 
ISR(TIMER0_COMPA_vect){
255
 
  sei();                      // Дадим возможность обработать прерывания от USB...
256
 
  PointNo++;
257
 
  GetADC = true;
258
 
}
259
 
 
260
 
//------------------------------------------------------------------------------
261
 
/*! Обработчик прерывания INT6.
262
 
*/
263
 
ISR(INT6_vect){
264
 
  sei();                  // Дадим возможность обработать прерывания от USB...
265
 
  StartDelay();
266
 
}