Так всё ок! И в правду на паузе шустрее стала прокрутка и вообще.
убери из этой функции первую строку. по идее фпс должен прилично увеличиться. я ж вроде дал функцию без этой строки... закомментируй, а лучше удали нафик первую строку if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; четыре сравнения, логические операции - это все не нужно тут. это проверка, не вылазит ли точка за пределы экрана. нужно избавиться от нее. просто проверь, не будет ли снова вылетать NAN. если будет - я найду его и убью))
и будет еще шустрее... продолжать?)) или хватит? топик загадим) особенно я... надо уходить из топика. отписаться. я вообще сюда случайно иногда захожу. не отписался еще)
а в самом низу 3-я строка снизу, сразу под // == Отрисовка графика == // меняй строку на
из за неё виснет после нажатия кнопки входа в оцил и всё. строку if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; удалил и NAN НЕ возвращается в опорном 5.0. :) (((( Можно на месенджер перейти чтобы топик не засыпать, я из Белки (могу номер сбросить). Остальные коды проглотила и летает ещё быстрее!!!
Последний изменил так и всё заработало! СПАСИБО!!! ВИДЕО
for (uint8_t x = 0; x < 92; x++) drawLine(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, x + 4, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
progrik пишет:
NAN. если будет - я найду его и убью))
Убивай))) хз где оно... появляется спантанно иногда при включении с кнопки. Добавил код авто-вход в осцил через 15 секунд/ и ок.
#define BUFSIZE 800
#define history 50
volatile int cur_index = 0; //переменная для отсчета замеров
volatile int StartIndex = 0; // номер замера с которого нужно выводить результат (считается так: (замер сработки триггера-предистория))
volatile byte prev_data; // предыдущее состояние шины
volatile byte pattern_mask; // маска для события PATTERN
volatile byte pattern_value; // ЗНАЧЕНИЕ состояния для события PATTERN
volatile boolean trigger_event = false; //признак сработки триггера
volatile int time_disc = 0; // время выборки 1-го значения
unsigned long prevMillis, curMillis;
enum triggerEvents {BURST, MASTER_RISE, MASTER_FALL, PATTERN}; //именнованный список триггеров-событий
bool flag = 0;
// Пины экранчика
#define RES 3
#define CS 4
#define Data 6
#define Clock 7
#define swap(a, b) { int t = a; a = b; b = t; }
#include <FreqCount.h>
#include <math.h>
#include <PWM.h>
// Настройки пользователя - можно менять
#define OVERCLOCK 16 // частота на которой работает Ардуино
float VCC = 5.0; // напряжение питания
#define KEY_L 11 // кнопка ЛЕВО (можно любой пин)
#define KEY_OK 12 // кнопка ОК (можно любой пин)
#define KEY_R 13 // кнопка ПРАВО (можно любой пин)
#define VBAT A1 // любой свободный аналоговый пин для измерения напряжения АКБ
#define TempC A0 // любой свободный аналоговый пин для измерения температуры
#define KEY_DELAY 200
#define LCDX 96
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "ОСЦИЛЛОГРАФ"; // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его
const char string_1[] PROGMEM = " ";
const char string_2[] PROGMEM = "VБат.= ";
const char string_3[] PROGMEM = "Temп.= ";
const char string_4[] PROGMEM = " Pause ";
// Теперь создаем таблицу с отсылками к этим строкам:
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4};
char buffer[11]; // массив должен быть достаточно велик, чтобы вместить даже самую большую строку
byte mode = 0; // пункт главного меню
byte menu = 0; // пункт меню
byte adcBuf[BUFSIZE];
byte vSync = 0; // уровень синхронизации
bool vRef = 1; // флаг опорного напряжения
bool pause = 0; // флаг режима паузы
bool avtorazv=1; // Автоматический выбор развертки
byte TextColor = 1;
byte razv = 0;
byte trig = 0;
int kdel=5; //bulat автопредел 1,1/0,22 вольта
int osc=50; // авто вкл. режима осциллографа (секунды)
int grOffset = 0; // смещение графика в рабочем режиме
byte vMax, vMin; // максимальное и минимальное напряжение сигнала
int temp = 0; // временная переменная***
unsigned long count = 1;
byte LCD_RAM[96 * 9]; // 96 * 9
static const char font[] PROGMEM = {
//HEX B DEC переводим
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x20 space
0x00, 0x00, 0x5f, 0x00, 0x00 , // 0x21 !
0x00, 0x07, 0x00, 0x07, 0x00 , // 0x22 "
0x14, 0x7f, 0x14, 0x7f, 0x14 , // 0x23 #
0x24, 0x2a, 0x7f, 0x2a, 0x12 , // 0x24 $
0x23, 0x13, 0x08, 0x64, 0x62 , // 0x25 %
0x36, 0x49, 0x55, 0x22, 0x50 , // 0x26 &
0x00, 0x05, 0x03, 0x00, 0x00 , // 0x27 '
0x00, 0x1c, 0x22, 0x41, 0x00 , // 0x28 (
0x00, 0x41, 0x22, 0x1c, 0x00 , // 0x29 )
0x14, 0x08, 0x3e, 0x08, 0x14 , // 0x2a *
0x08, 0x08, 0x3e, 0x08, 0x08 , // 0x2b +
0x00, 0x50, 0x30, 0x00, 0x00 , // 0x2c ,
0x08, 0x08, 0x08, 0x08, 0x08 , // 0x2d -
0x00, 0x60, 0x60, 0x00, 0x00 , // 0x2e .
0x20, 0x10, 0x08, 0x04, 0x02 , // 0x2f /
0x3e, 0x51, 0x49, 0x45, 0x3e , // 0x30 0
0x00, 0x42, 0x7f, 0x40, 0x00 , // 0x31 1
0x42, 0x61, 0x51, 0x49, 0x46 , // 0x32 2
0x21, 0x41, 0x45, 0x4b, 0x31 , // 0x33 3
0x18, 0x14, 0x12, 0x7f, 0x10 , // 0x34 4
0x27, 0x45, 0x45, 0x45, 0x39 , // 0x35 5
0x3c, 0x4a, 0x49, 0x49, 0x30 , // 0x36 6
0x01, 0x71, 0x09, 0x05, 0x03 , // 0x37 7
0x36, 0x49, 0x49, 0x49, 0x36 , // 0x38 8
0x06, 0x49, 0x49, 0x29, 0x1e , // 0x39 9
0x00, 0x36, 0x36, 0x00, 0x00 , // 0x3a :
0x00, 0x56, 0x36, 0x00, 0x00 , // 0x3b ;
0x08, 0x14, 0x22, 0x41, 0x00 , // 0x3c <
0x14, 0x14, 0x14, 0x14, 0x14 , // 0x3d =
0x00, 0x41, 0x22, 0x14, 0x08 , // 0x3e >
0x02, 0x01, 0x51, 0x09, 0x06 , // 0x3f ?
0x32, 0x49, 0x79, 0x41, 0x3e , // 0x40 @
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x41 A
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x42 B
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x43 C
0x7f, 0x41, 0x41, 0x22, 0x1c , // 0x44 D
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x45 E
0x7f, 0x09, 0x09, 0x09, 0x01 , // 0x46 F
0x3e, 0x41, 0x49, 0x49, 0x7a , // 0x47 G
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x48 H
0x00, 0x41, 0x7f, 0x41, 0x00 , // 0x49 I
0x20, 0x40, 0x41, 0x3f, 0x01 , // 0x4a J
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x4b K
0x7f, 0x40, 0x40, 0x40, 0x40 , // 0x4c L
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x4d M
0x7f, 0x04, 0x08, 0x10, 0x7f , // 0x4e N
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x4f O
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x50 P
0x3e, 0x41, 0x51, 0x21, 0x5e , // 0x51 Q
0x7f, 0x09, 0x19, 0x29, 0x46 , // 0x52 R
0x46, 0x49, 0x49, 0x49, 0x31 , // 0x53 S
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x54 T
0x3f, 0x40, 0x40, 0x40, 0x3f , // 0x55 U
0x1f, 0x20, 0x40, 0x20, 0x1f , // 0x56 V
0x3f, 0x40, 0x38, 0x40, 0x3f , // 0x57 W
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x58 X
0x07, 0x08, 0x70, 0x08, 0x07 , // 0x59 Y
0x61, 0x51, 0x49, 0x45, 0x43 , // 0x5a Z
0x00, 0x7f, 0x41, 0x41, 0x00 , // 0x5b [
0x02, 0x04, 0x08, 0x10, 0x20 , // 0x5c backslash
0x00, 0x41, 0x41, 0x7f, 0x00 , // 0x5d ]
0x04, 0x02, 0x01, 0x02, 0x04 , // 0x5e ^
0x40, 0x40, 0x40, 0x40, 0x40 , // 0x5f _
0x00, 0x01, 0x02, 0x04, 0x00 , // 0x60 `
0x20, 0x54, 0x54, 0x54, 0x78 , // 0x61 a
0x7f, 0x48, 0x44, 0x44, 0x38 , // 0x62 b
0x38, 0x44, 0x44, 0x44, 0x20 , // 0x63 c
0x38, 0x44, 0x44, 0x48, 0x7f , // 0x64 d
0x38, 0x54, 0x54, 0x54, 0x18 , // 0x65 e
0x08, 0x7e, 0x09, 0x01, 0x02 , // 0x66 f
0x0c, 0x52, 0x52, 0x52, 0x3e , // 0x67 g
0x7f, 0x08, 0x04, 0x04, 0x78 , // 0x68 h
0x00, 0x44, 0x7d, 0x40, 0x00 , // 0x69 i
0x20, 0x40, 0x44, 0x3d, 0x00 , // 0x6a j
0x7f, 0x10, 0x28, 0x44, 0x00 , // 0x6b k
0x00, 0x41, 0x7f, 0x40, 0x00 , // 0x6c l
0x7c, 0x04, 0x18, 0x04, 0x78 , // 0x6d m
0x7c, 0x08, 0x04, 0x04, 0x78 , // 0x6e n
0x38, 0x44, 0x44, 0x44, 0x38 , // 0x6f o
0x7c, 0x14, 0x14, 0x14, 0x08 , // 0x70 p
0x08, 0x14, 0x14, 0x18, 0x7c , // 0x71 q
0x7c, 0x08, 0x04, 0x04, 0x08 , // 0x72 r
0x48, 0x54, 0x54, 0x54, 0x20 , // 0x73 s
0x04, 0x3f, 0x44, 0x40, 0x20 , // 0x74 t
0x3c, 0x40, 0x40, 0x20, 0x7c , // 0x75 u
0x1c, 0x20, 0x40, 0x20, 0x1c , // 0x76 v
0x3c, 0x40, 0x30, 0x40, 0x3c , // 0x77 w
0x44, 0x28, 0x10, 0x28, 0x44 , // 0x78 x
0x0c, 0x50, 0x50, 0x50, 0x3c , // 0x79 y
0x44, 0x64, 0x54, 0x4c, 0x44 , // 0x7a z
0x00, 0x08, 0x36, 0x41, 0x00 , // 0x7b {
0x00, 0x00, 0x7f, 0x00, 0x00 , // 0x7c |
0x00, 0x41, 0x36, 0x08, 0x00 , // 0x7d }
0x10, 0x08, 0x08, 0x10, 0x08 , // 0x7e ~
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x7f
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x80 A // Русские символы
0x7f, 0x49, 0x49, 0x49, 0x33 , // 0x81 Б
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x82 В
0x7f, 0x01, 0x01, 0x01, 0x03 , // 0x83 Г
0xe0, 0x51, 0x4f, 0x41, 0xff , // 0x84 Д
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x85 E
0x77, 0x08, 0x7f, 0x08, 0x77 , // 0x86 Ж
0x41, 0x49, 0x49, 0x49, 0x36 , // 0x87 З
0x7f, 0x10, 0x08, 0x04, 0x7f , // 0x88 И
0x7c, 0x21, 0x12, 0x09, 0x7c , // 0x89 Й
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x8A K
0x20, 0x41, 0x3f, 0x01, 0x7f , // 0x8B Л
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x8C M
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x8D H
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x8E O
0x7f, 0x01, 0x01, 0x01, 0x7f , // 0x8F П
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x90 P
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x91 C
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x92 T
0x47, 0x28, 0x10, 0x08, 0x07 , // 0x93 У
0x1c, 0x22, 0x7f, 0x22, 0x1c , // 0x94 Ф
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x95 X
0x7f, 0x40, 0x40, 0x40, 0xff , // 0x96 Ц
0x07, 0x08, 0x08, 0x08, 0x7f , // 0x97 Ч
0x7f, 0x40, 0x7f, 0x40, 0x7f , // 0x98 Ш
0x7f, 0x40, 0x7f, 0x40, 0xff , // 0x99 Щ
0x01, 0x7f, 0x48, 0x48, 0x30 , // 0x9A Ъ
0x7f, 0x48, 0x30, 0x00, 0x7f , // 0x9B Ы
0x00, 0x7f, 0x48, 0x48, 0x30 , // 0x9C Э
0x22, 0x41, 0x49, 0x49, 0x3e , // 0x9D Ь
0x7f, 0x08, 0x3e, 0x41, 0x3e , // 0x9E Ю
0x46, 0x29, 0x19, 0x09, 0x7f , // 0x9F Я
0x20, 0x54, 0x54, 0x54, 0x78 , // 0xA0 a
0x3c, 0x4a, 0x4a, 0x49, 0x31 , // 0xA1 б
0x7c, 0x54, 0x54, 0x54, 0x28 , // 0xA2 в
0x7c, 0x04, 0x04, 0x04, 0x0c , // 0xA3 г
0xe0, 0x54, 0x4c, 0x44, 0xfc , // 0xA4 д
0x38, 0x54, 0x54, 0x54, 0x18 , // 0xA5 e
0x6c, 0x10, 0x7c, 0x10, 0x6c , // 0xA6 ж
0x44, 0x44, 0x54, 0x54, 0x28 , // 0xA7 з
0x7c, 0x20, 0x10, 0x08, 0x7c , // 0xA8 и
0x7c, 0x41, 0x22, 0x11, 0x7c , // 0xA9 й
0x7c, 0x10, 0x10, 0x28, 0x44 , // 0xAA к
0x20, 0x44, 0x3c, 0x04, 0x7c , // 0xAB л
0x7c, 0x08, 0x10, 0x08, 0x7c , // 0xAC м
0x7c, 0x10, 0x10, 0x10, 0x7c , // 0xAD н
0x38, 0x44, 0x44, 0x44, 0x38 , // 0xAE o
0x7c, 0x04, 0x04, 0x04, 0x7c , // 0xAF п
0x7C, 0x14, 0x14, 0x14, 0x08 , // 0xB0 p
0x38, 0x44, 0x44, 0x44, 0x20 , // 0xB1 c
0x04, 0x04, 0x7c, 0x04, 0x04 , // 0xB2 т
0x0C, 0x50, 0x50, 0x50, 0x3C , // 0xB3 у
0x30, 0x48, 0xfc, 0x48, 0x30 , // 0xB4 ф
0x44, 0x28, 0x10, 0x28, 0x44 , // 0xB5 x
0x7c, 0x40, 0x40, 0x40, 0xfc , // 0xB6 ц
0x0c, 0x10, 0x10, 0x10, 0x7c , // 0xB7 ч
0x7c, 0x40, 0x7c, 0x40, 0x7c , // 0xB8 ш
0x7c, 0x40, 0x7c, 0x40, 0xfc , // 0xB9 щ
0x04, 0x7c, 0x50, 0x50, 0x20 , // 0xBA ъ
0x7c, 0x50, 0x50, 0x20, 0x7c , // 0xBB ы
0x7c, 0x50, 0x50, 0x20, 0x00 , // 0xBC ь
0x28, 0x44, 0x54, 0x54, 0x38 , // 0xBD э
0x7c, 0x10, 0x38, 0x44, 0x38 , // 0xBE ю
0x08, 0x54, 0x34, 0x14, 0x7c , // 0xBF я
};
//********************************************************
// ==== Считывание напряжения питания ардуинки (Vcc) ====
#define Vref11 1.095 // для точной подстройки результата измерений
float ReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // устанавливаем вход АЦП на VCC !!!
delay(1); // задержка для устаканивания АЦП. Можно её избежать, если ADMUX как в строке выше (не менялся)
ADCSRA |= _BV(ADSC); // запуск АЦП преобразования
while (bit_is_set(ADCSRA, ADSC)); // ждем, пока АЦП отработает (выставит бит)
return (Vref11 * 1023.0) / (ADCL | (ADCH << 8)); // результат преобразования в вольтах
}
/////// ==== Температура ==== ////////
double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000)); // 10000=10кОм Для подстройки правим 10000.
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15; // Kelvin to Celcius
return Temp;
}
void setup() {
pinMode(KEY_OK, INPUT); pinMode(KEY_L, INPUT); pinMode(KEY_R, INPUT); // настраиваем кнопки на вход
digitalWrite(KEY_OK, HIGH); digitalWrite(KEY_L, HIGH); digitalWrite(KEY_R, HIGH); // подтяжка к плюсу питания
VCC = ReadVcc();
Inicialize(); //Инициализация дисплея
Clear_LCD();
for (byte i = 0; i < 3; i++)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте
print(10, i * 10, 1, (buffer));
//delay( 500 );
}
Update();
// delay(KEY_DELAY);
while (digitalRead(KEY_OK)) { // цикл, пока не нажали кнопку ОК
Update();
// Если не нажата 10 сек кнопка ок вход в режим осцилоографа автоматом
osc--;
if (osc==0) break;
////////// Выводим показание /////////
float_print(60, 20, 1, analogRead(VBAT)*VCC/1024,1); //Вольтаж батареи
float_print(55, 40, 1, analogRead(TempC), 1); // выводим на экран показание Температуры
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[3]))); // пишем слово "Температура"
print(10, 40, 1, (buffer));
delay( 300 );
} // цикл нажатия ОК
// нажали кнопку ОК из меню, инициализируем и выходим из меню
count = 0; //countX = 0; // восстанавливаем на всякий случай переменные
if (mode == 0) FreqCount.begin(1000);
if (mode == 1) {
InitTimersSafe();
}
if (mode == 2) {
InitTimersSafe();
}
if (mode == 4 || mode == 5) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки
for (char a=37; a>0; a-=2);
}
// беcконечный цикл - по сути прыгаем в подпрограммы
void loop() {
switch (mode) {
// Прыгаем в выбранный режим из главного меню
case 0 : Oscil(); break; // "выпадаем" в осцилл
}
}
// === Читаем с АЦП данные и помещаем их в буфер === //
void ReadAdc() {
if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7)
ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4)
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
adcBuf[i] = ADCH; // записываем данные в массив
}
delay(0.3 * BUFSIZE); // компенсация задержки по сравнению с разверткой 0...
} else { // развертка с задержками (delay)
ADCSRA = 0b11100111; // делитель на /128
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
delayMicroseconds(500); // делаем задержку
adcBuf[i] = ADCH; // записываем данные в массив
}
}
}
// === Чтение цифровых данных со всего порта C (A0...A5) === //
/*void ReadDig() {
if (razv == 9) {
for (int i = 0; i < BUFSIZE; i++) adcBuf[i] = PINC; // быстро читаем данные
} else {
for (int i = 0; i < BUFSIZE; i++) {
adcBuf[i] = PINC; // читаем данные
delayMicroseconds((9 - razv) * 100);
}
}
}*/
// ==== функция вывода float ====
void float_print(byte x, byte y, boolean color, float num, byte zn) { // последняя переменная- кол знаков после запятой
char c[20];
long d = num;
byte m = 1;
while (d > 9) {
d = d / 10;
m++;
}
print(x, y, color, dtostrf(num, m, zn, c));
}
/*int GetCountsOfDigits(int n) //найти количество цифр в числе <a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>
{
return n < 10 ? 1 :
n < 100 ? 2 :
n < 1000 ? 3 :
n < 10000 ? 4 :
n < 100000 ? 5 :
n < 1000000 ? 6 :
n < 10000000 ? 7 :
n < 100000000 ? 8 :
n < 1000000000 ? 9 : 10;
}*/
// ==== найти количество цифр в числе <a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>
/*static int stringSize(long x) {
long p = 10;
for (int i = 1; i < 19; i++) {
if (x < p)
return i;
p = 10 * p;
}
return 19;
}*/
void vivod(byte x, byte y, byte n, byte k) { // //Печать цифры размером 24х48 пикселя (x, y, цифра, размер (1-24х48, 2-12х24))
if ((n != 1) && (n != 4)) {
fillRect(x + 3 / k, y, 15 / k, 5 / k, 1 ); // сегмент A
}
if ((n != 5) && (n != 6)) {
fillRect(x + 16 / k, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент B
}
if (n != 2) {
fillRect(x + 16 / k, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент C
}
if ((n != 1) && (n != 4) && (n != 7)) {
fillRect(x + 3 / k, y + 42 / k, 15 / k, 5 / k, 1 ); // сегмент D
}
if ((n == 0) || (n == 2) || (n == 6) || (n == 8)) {
fillRect(x, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент E
}
if ((n != 1) && (n != 2) && (n != 3) && (n != 7)) {
fillRect(x, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент F
}
if ((n != 0) && (n != 1) && (n != 7)) {
fillRect(x + 3 / k, y + 21 / k, 15 / k, 5 / k, 1 ); // сегмент G
}
}
//====================================================указатель меню
/*void ukazatel() {
fillRect(1, 1, 8, 60, 0);
for (byte i = 0; i < 4; i++) { // указатель меню
drawLine(1 + i, mode * 10 + i, 1 + i, mode * 10 + 6 - i, 1);
}
Update();
delay(KEY_DELAY);
}
*/
//===================================================Инициализация дисплея
void Inicialize() {
pinMode(RES, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(Data, OUTPUT);
pinMode(Clock, OUTPUT);
// Инициализация дисплея
dWrite(RES, 1);
dWrite(Clock, 0);
dWrite(Data, 0);
dWrite(CS, 0);
delay(20);
dWrite(CS, 1);
SendByte(0, 0x2F); // Power control set(charge pump on/off)
SendByte(0, 0xA4);
SendByte(0, 0xAF); // экран вкл/выкл
//Clear_LCD();
//Update();
}
//=======================================================Управление пинами
void dWrite(byte pin, byte val) {
byte bit = digitalPinToBitMask(pin);
volatile byte *out;
out = portOutputRegister(digitalPinToPort(pin));
(val) ? *out |= bit : *out &= ~bit;
}
//=========================================================Отправка 9 байт
void SendByte(byte mode, byte c) {
dWrite(CS, 0);
(mode) ? dWrite(Data, 1) : dWrite(Data, 0);
dWrite(Clock, 1);
for (byte i = 0; i < 8; i++) {
dWrite(Clock, 0);
(c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0);
dWrite(Clock, 1);
c <<= 1;
}
dWrite(Clock, 0);
}
//======================================================Очистка дисплея
void Clear_LCD() {
for (int index = 0; index < 864 ; index++) {
LCD_RAM[index] = (0x00);
}
}
//=====================================================Обновить дисплей
void Update() {
for (byte p = 0; p < 9; p++) {
SendByte(0, 0xB0 | p);
SendByte(0, 0x00);
SendByte(0, 0x10);
for (byte col = 0; col < 96; col++) {
SendByte(1, LCD_RAM[(96 * p) + col]);
}
}
}
//===================================================Нарисовать пиксель
void drawPixel (byte x, byte y, boolean color) {
// if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; // NAN херня
if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8);
else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8);
}
//=====================================================Нарисовать букву
void drawChar(byte x, byte y, boolean color, unsigned char c) {
if ((x >= 96) || (y >= 68) || ((x + 4) < 0) || ((y + 7) < 0)) return;
if (c < 128) c = c - 32;
if (c >= 144 && c <= 175) c = c - 48;
if (c >= 128 && c <= 143) c = c + 16;
if (c >= 176 && c <= 191) c = c - 48;
if (c > 191) return;
for (byte i = 0; i < 6; i++ ) {
byte line;
(i == 5) ? line = 0x0 : line = pgm_read_byte(font + (c * 5) + i); // line = EEPROM.read((c * 5) + i);
for (byte j = 0; j < 8; j++) {
// (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color);
if(line & 0x1)
{
drawPixel(x + i, y + j, color);
}
else
{
drawPixel(x + i, y + j, !color);
}
line >>= 1;
}
}
}
//========================================================Вывод строки
void print(byte x, byte y, boolean color, char *str) {
unsigned char type = *str;
if (type >= 128) x = x - 3;
while (*str) {
drawChar(x, y, color, *str++);
unsigned char type = *str;
(type >= 128) ? x = x + 3 : x = x + 6;
}
}
//========================================================Вывод числовых значений
void print(byte x, byte y, boolean color, long num) {
char c[20];
print(x, y, color, ltoa(num, c, 10));
}
//====================================================Рисование линии
void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) {
int steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int err = dx / 2;
int ystep;
(y0 < y1) ? ystep = 1 : ystep = -1;
for (; x0 <= x1; x0++) {
// (steep) ? drawPixel(y0, x0, color) : drawPixel(x0, y0, color);
if(steep)
{
drawPixel(y0, x0, color);
}
else
{
drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
/////////////////добавь где-то, например, под функцией DrawLine такую функцию:////////////////////////////
void drawLineUltraFast(byte x, byte y0, byte y1, boolean color) {
if(y0 < y1)
{
byte tmp = y0;
y0 = y1;
y1 = tmp;
}
while(y0 <= y1);
{
drawPixel(x, y0, color);
y0++;
}
}
//========================================Рисование вертикальной линии
void drawFastVLine(byte x, byte y, byte h, boolean color) {
drawLine(x, y, x, y + h - 1, color);
}
//======================================Рисование горизонтальной линии
void drawFastHLine(byte x, byte y, byte w, boolean color) {
drawLine(x, y, x + w - 1, y, color);
}
//=====================================Рисование залитый прямоугольник
void fillRect(byte x, byte y, byte w, byte h, boolean color) {
for (byte i = x; i < x + w; i++) {
drawFastVLine(i, y, h, color);
}
}
//=====================================Рисование битового нолика
void printnull(byte a, byte i) {
drawPixel(29 + a - i * 4, 64, 1);
drawFastVLine(28 + a - i * 4, 65, 2, 1); // и вывести биты на дисплей
drawFastVLine(30 + a - i * 4, 65, 2, 1);
drawPixel(29 + a - i * 4, 67, 1);
}
// === Осциллоскоп === //
void Oscil() {
// установка опорного напряжения АЦП и настройка входа АЦП
ADMUX = vRef ? 0b01100011 : 0b11100011;
label_ReadAdc:
// === Обработка кнопок === //
if (!digitalRead(KEY_L)) switch (menu) { // кнопка лево:)
case 0 : razv--; if (razv == 255) razv = 6; break; // меняем развертку
case 1 : grOffset -= 20; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе
}
if (!digitalRead(KEY_R)) switch (menu) { // кнопка право:)
case 0 : razv++; if (razv == 7) razv = 0; break; // меняем развертку
case 1 : grOffset += 20; if (grOffset > BUFSIZE - LCDX) grOffset = BUFSIZE - LCDX; break; // листаем график в паузе
}
if (!digitalRead(KEY_OK)) switch (++menu) {
case 1: grOffset = 0; pause = 1; break; // вход в паузу - антидребезг типа
case 2: menu = 0; pause = 0; break; // перебор меню
}
////////////////
// === Ведём рассчеты === //
if (!pause) { // если нет паузы
ReadAdc(); // то снимаем осциллограмму
// == Вычисляем максимальное и минимальное значение сигнала == //
vMax = 0; vMin = 0xFF;
for (int y = 1; y < 255; y++) {
if (vMax < adcBuf[y]) vMax = adcBuf[y]; // пока 255, но надо экспериментировать
if (vMin > adcBuf[y]) vMin = adcBuf[y];
}
vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала
// == Определение точки синхронизации == //
bool flagZero = 0; grOffset = 0; // сброс флага и точки синхронизации
// Ищем перепад от меньшего уровня к большему
for (int y = 1; y < BUFSIZE - LCDX; y++) { // смотрим весь массив данных АЦП
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг
if (flagZero && adcBuf[y] > vSync) {
grOffset = y; // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла
break;
}
}
// === Считаем частоту сигнала === //
if (vRef && vMax * VCC / 255 > 2.7) { // если можем замерить аппаратно - меряем
if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала
} else { // === Меряем частоту сигнала программно === //
flagZero = 0; count = 0; // сброс флага и счетчика
for (int y = grOffset; y < BUFSIZE - LCDX; y++) { // смотрим массив от точки синхронизации до конца
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг
if (flagZero && adcBuf[y] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период
switch (razv) { // считем частоту периода
case 6: count = 1000000 / ((y - grOffset - 1) * 3.25); break; // делитель 4
case 5: count = 1000000 / ((y - grOffset) * 3.25) / 2; break; // делитель 8
case 4: count = 1000000 / ((y - grOffset) * 3.25) / 4; break; // делитель 16
case 3: count = 1000000 / ((y - grOffset) * 3.25) / 8; break; // делитель 32
case 2: count = 1000000 / ((y - grOffset) * 3.25) / 16; break; // делитель 64
case 1: count = 1000000 / ((y - grOffset) * 3.25) / 32; break; // делитель 128
case 0: count = 1000000 / ((y - grOffset) * 510); break; // делитель 128 тоже
}
break;
}
}
}
count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы
} // закончили вести рассчеты
Clear_LCD(); // чистим экран...
// === Отрисовка меню осцилла ===
// if (vRef) TextColor = 0; else TextColor = 1;
if (vRef) float_print(0, 0, 1, VCC, 1); else {
if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "0.2");
}
if (menu == 0) TextColor = 0; else TextColor = 1; drawChar(21, 0, 1, 'р'); print(27, 0, 1, razv);
if (menu == 1) { // тут задержка для компенсации с остальными задержками
delay(100);
// print(48, 0, 0, " Pause ");
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); // необходимые функции и расшифровки, просто скопируйте
print(48, 0, 0, (buffer));
} else TextColor = 1;
if (!pause) float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты
else { // рисуем прокрутку в режиме паузы
temp = grOffset / 8;
drawFastHLine(temp, 10, 6, 1); drawFastHLine(temp, 9, 6, 1);
} // шкала прокрутки
if (vRef && vMax * VCC / 255 > 2.7) drawChar(37, 0, 1, 'А'); // если замер - "а"ппаратный
else drawChar(37, 0, 1, 'П'); // иначе "п"програмный
float_print(73, 12, 1, vMax * (vRef ? VCC : 1.1) / 255, 2); // рисуем максимальное напряжение сигнала
float_print(78, 54, 1, vMin * (vRef ? VCC : 1.1) / 255, 1); // рисуем минимальное напряжение сигнала
if (vMax==0xFF) for(int y=10; y<68; y++) drawFastHLine( 0, y, 5, 5); // превышение максимума АЦП
// == Отрисовка сетки == //
for (byte i = 11; i < 68; i = i + 14) {
drawFastHLine( 0, i, 2, 1); // черточки слева
}
for (byte i = 67; i > 10; i = i - 4) {
drawPixel(24, i, 1);
drawPixel(48, i, 1);
drawPixel(72, i, 1);
}
for (byte i = 8; i < 96; i = i + 4) {
drawPixel(i, 39, 1);
}
///////////////авто razv//////////////
if (avtorazv)
#define PER 1.3
if (count > 3823.3*PER) razv = 6; else
if (count > 1934.5*PER) razv = 5; else
if (count > 0969.3*PER) razv = 4; else
if (count > 0486.8*PER) razv = 3; else
if (count > 0245.8*PER) razv = 2; else
if (count > 0120.1*PER) razv = 1; else razv = 0;
//bulat если зашкаливает включаем предел 5 в
if (vMax==255){
if (vRef==0)
{
vRef=1;
ADMUX = 0b01100011;// выбор внутреннего опорного 5.0 В
goto label_ReadAdc;
}
}
//bulat если 5 в и уровень менее 1,1 в то вкл предел 1,1 в
if (vMax<=55){
if (vRef==1)
{
vRef=0;
ADMUX = 0b11100011;// выбор внутреннего опорного 1,1В
goto label_ReadAdc;
}
}
//bulat здесь автопредел 1,1/0,22 в,программный
kdel=5;
if (vMax<=55){
if (vRef==0)
{
kdel=1;
}
}
// == Отрисовка графика == //
// for (uint8_t x = 0; x < 92; x++) drawLineUltraFast(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
for (uint8_t x = 0; x < 92; x++) drawLine(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, x + 4, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
Update();
}
smokok верни как я говорил, ниже // == Отрисовка графика == // строку c drawLineUltraFast раскомментируй, с drawLine закомментируй. а в самой функции drawLineUltraFast в строке drawPixel(x, y0, color); поменяй в вызове функции x и y0 местами. вот так: drawPixel(y0, x, color); и пробуй.
вижу, на перемотке раза в два быстрее стало, но что-то все равно не то. тут весь код написан так, чтобы убить скорость. был бы у мну такой дисплей - за 5 минут порешал бы его и вывел на орбиту)) но так - тяжеловато.
вообщем, меняй снова и пробуй. там иксы с игреками перепутаны и в них черт ногу сломит... скорее всего с перепутанными х и у прога лезла в область памяти за пределами выделенной, из за этого крешилось...
как я и говорил, тут все написано как для демонстрационной демонстрации демо версии демо прибора для демонстрации демо. все переписывать я не буду. а нужно бы. не мне. тому, кому нужно)) поиграй с чем есть, а мне пока нужно свою работу работать... не запустится функция drawLineUltraFast - верни все взад)) без дисплея совсем грустно такой фигней заниматься.
ЗЫ: а зачем тебе это? у тебя же на фотке дсо138 с паршивкой от GFX вроде. как гласит реклама, "зачем вам этот геморрой?"))
не запустится функция drawLineUltraFast - верни все взад)) без дисплея совсем грустно такой фигней заниматься.
Вернул, а то виснет даже во время авто-входа. Был бы я рядом, дал бы дисплей погонять, за одно и отдохнул бы))).
progrik пишет:
ЗЫ: а зачем тебе это? у тебя же на фотке дсо138 с паршивкой от GFX вроде. как гласит реклама, "зачем вам этот геморрой?"))
Зачем... Первое это интересно и так же Под этот экран думал тахометр для мотопеда собрать, но так бедно скетча нет и чтоб не пропало осцил вгрузил. Соберу чтоб не валялось, подганю кому нибудь экслюзивчик. Да и многим пригодятся Ваши советы и работа других людей с этого форума для самоделки. GFX конечно далеко впереди (туда бы ещё в паршивку авторазв. добавить), но с ProMini 328P не нужно парится с ремонтом для кого то, если сломалась подменил на новый модуль и всё, не жалко))). Как то так))). Ещё раз Спасибо за советы!!!
а где делось объявление inline __attribute__((always_inline)) voiddrawPixel(...??? у тебя просто voiddrawPixel()... ДОПИШИ чтоб стало inline __attribute__((always_inline)) voiddrawPixel(....
и я нашел... перепутал... вместо "<" нужно ">" ... одна ошибка, и точки не выводятся... поменяй функцию drawLineUltraFast
smokok блин. я после while(y0 <= y1) случайно запилил точку с запятой, а вместо "больше" поставил "меньше". в 3-х строках две ошибки. учитесь, пока я жив))
а не компилится - та ладно)... сейчас дам полный код, у меня компилируется
#define BUFSIZE 800
#define history 50
volatile int cur_index = 0; //переменная для отсчета замеров
volatile int StartIndex = 0; // номер замера с которого нужно выводить результат (считается так: (замер сработки триггера-предистория))
volatile byte prev_data; // предыдущее состояние шины
volatile byte pattern_mask; // маска для события PATTERN
volatile byte pattern_value; // ЗНАЧЕНИЕ состояния для события PATTERN
volatile boolean trigger_event = false; //признак сработки триггера
volatile int time_disc = 0; // время выборки 1-го значения
unsigned long prevMillis, curMillis;
enum triggerEvents {BURST, MASTER_RISE, MASTER_FALL, PATTERN}; //именнованный список триггеров-событий
bool flag = 0;
// Пины экранчика
#define RES 3
#define CS 4
#define Data 6
#define Clock 7
#define swap(a, b) { int t = a; a = b; b = t; }
#include <FreqCount.h>
#include <math.h>
#include <PWM.h>
// Настройки пользователя - можно менять
#define OVERCLOCK 16 // частота на которой работает Ардуино
float VCC = 5.0; // напряжение питания
#define KEY_L 11 // кнопка ЛЕВО (можно любой пин)
#define KEY_OK 12 // кнопка ОК (можно любой пин)
#define KEY_R 13 // кнопка ПРАВО (можно любой пин)
#define VBAT A1 // любой свободный аналоговый пин для измерения напряжения АКБ
#define TempC A0 // любой свободный аналоговый пин для измерения температуры
#define KEY_DELAY 200
#define LCDX 96
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "ОСЦИЛЛОГРАФ"; // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его
const char string_1[] PROGMEM = " ";
const char string_2[] PROGMEM = "VБат.= ";
const char string_3[] PROGMEM = "Temп.= ";
const char string_4[] PROGMEM = " Pause ";
// Теперь создаем таблицу с отсылками к этим строкам:
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4};
char buffer[11]; // массив должен быть достаточно велик, чтобы вместить даже самую большую строку
byte mode = 0; // пункт главного меню
byte menu = 0; // пункт меню
byte adcBuf[BUFSIZE];
byte vSync = 0; // уровень синхронизации
bool vRef = 1; // флаг опорного напряжения
bool pause = 0; // флаг режима паузы
bool avtorazv=1; // Автоматический выбор развертки
byte TextColor = 1;
byte razv = 0;
byte trig = 0;
int kdel=5; //bulat автопредел 1,1/0,22 вольта
int osc=50; // авто вкл. режима осциллографа (секунды)
int grOffset = 0; // смещение графика в рабочем режиме
byte vMax, vMin; // максимальное и минимальное напряжение сигнала
int temp = 0; // временная переменная***
unsigned long count = 1;
byte LCD_RAM[96 * 9]; // 96 * 9
static const char font[] PROGMEM = {
//HEX B DEC переводим
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x20 space
0x00, 0x00, 0x5f, 0x00, 0x00 , // 0x21 !
0x00, 0x07, 0x00, 0x07, 0x00 , // 0x22 "
0x14, 0x7f, 0x14, 0x7f, 0x14 , // 0x23 #
0x24, 0x2a, 0x7f, 0x2a, 0x12 , // 0x24 $
0x23, 0x13, 0x08, 0x64, 0x62 , // 0x25 %
0x36, 0x49, 0x55, 0x22, 0x50 , // 0x26 &
0x00, 0x05, 0x03, 0x00, 0x00 , // 0x27 '
0x00, 0x1c, 0x22, 0x41, 0x00 , // 0x28 (
0x00, 0x41, 0x22, 0x1c, 0x00 , // 0x29 )
0x14, 0x08, 0x3e, 0x08, 0x14 , // 0x2a *
0x08, 0x08, 0x3e, 0x08, 0x08 , // 0x2b +
0x00, 0x50, 0x30, 0x00, 0x00 , // 0x2c ,
0x08, 0x08, 0x08, 0x08, 0x08 , // 0x2d -
0x00, 0x60, 0x60, 0x00, 0x00 , // 0x2e .
0x20, 0x10, 0x08, 0x04, 0x02 , // 0x2f /
0x3e, 0x51, 0x49, 0x45, 0x3e , // 0x30 0
0x00, 0x42, 0x7f, 0x40, 0x00 , // 0x31 1
0x42, 0x61, 0x51, 0x49, 0x46 , // 0x32 2
0x21, 0x41, 0x45, 0x4b, 0x31 , // 0x33 3
0x18, 0x14, 0x12, 0x7f, 0x10 , // 0x34 4
0x27, 0x45, 0x45, 0x45, 0x39 , // 0x35 5
0x3c, 0x4a, 0x49, 0x49, 0x30 , // 0x36 6
0x01, 0x71, 0x09, 0x05, 0x03 , // 0x37 7
0x36, 0x49, 0x49, 0x49, 0x36 , // 0x38 8
0x06, 0x49, 0x49, 0x29, 0x1e , // 0x39 9
0x00, 0x36, 0x36, 0x00, 0x00 , // 0x3a :
0x00, 0x56, 0x36, 0x00, 0x00 , // 0x3b ;
0x08, 0x14, 0x22, 0x41, 0x00 , // 0x3c <
0x14, 0x14, 0x14, 0x14, 0x14 , // 0x3d =
0x00, 0x41, 0x22, 0x14, 0x08 , // 0x3e >
0x02, 0x01, 0x51, 0x09, 0x06 , // 0x3f ?
0x32, 0x49, 0x79, 0x41, 0x3e , // 0x40 @
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x41 A
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x42 B
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x43 C
0x7f, 0x41, 0x41, 0x22, 0x1c , // 0x44 D
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x45 E
0x7f, 0x09, 0x09, 0x09, 0x01 , // 0x46 F
0x3e, 0x41, 0x49, 0x49, 0x7a , // 0x47 G
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x48 H
0x00, 0x41, 0x7f, 0x41, 0x00 , // 0x49 I
0x20, 0x40, 0x41, 0x3f, 0x01 , // 0x4a J
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x4b K
0x7f, 0x40, 0x40, 0x40, 0x40 , // 0x4c L
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x4d M
0x7f, 0x04, 0x08, 0x10, 0x7f , // 0x4e N
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x4f O
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x50 P
0x3e, 0x41, 0x51, 0x21, 0x5e , // 0x51 Q
0x7f, 0x09, 0x19, 0x29, 0x46 , // 0x52 R
0x46, 0x49, 0x49, 0x49, 0x31 , // 0x53 S
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x54 T
0x3f, 0x40, 0x40, 0x40, 0x3f , // 0x55 U
0x1f, 0x20, 0x40, 0x20, 0x1f , // 0x56 V
0x3f, 0x40, 0x38, 0x40, 0x3f , // 0x57 W
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x58 X
0x07, 0x08, 0x70, 0x08, 0x07 , // 0x59 Y
0x61, 0x51, 0x49, 0x45, 0x43 , // 0x5a Z
0x00, 0x7f, 0x41, 0x41, 0x00 , // 0x5b [
0x02, 0x04, 0x08, 0x10, 0x20 , // 0x5c backslash
0x00, 0x41, 0x41, 0x7f, 0x00 , // 0x5d ]
0x04, 0x02, 0x01, 0x02, 0x04 , // 0x5e ^
0x40, 0x40, 0x40, 0x40, 0x40 , // 0x5f _
0x00, 0x01, 0x02, 0x04, 0x00 , // 0x60 `
0x20, 0x54, 0x54, 0x54, 0x78 , // 0x61 a
0x7f, 0x48, 0x44, 0x44, 0x38 , // 0x62 b
0x38, 0x44, 0x44, 0x44, 0x20 , // 0x63 c
0x38, 0x44, 0x44, 0x48, 0x7f , // 0x64 d
0x38, 0x54, 0x54, 0x54, 0x18 , // 0x65 e
0x08, 0x7e, 0x09, 0x01, 0x02 , // 0x66 f
0x0c, 0x52, 0x52, 0x52, 0x3e , // 0x67 g
0x7f, 0x08, 0x04, 0x04, 0x78 , // 0x68 h
0x00, 0x44, 0x7d, 0x40, 0x00 , // 0x69 i
0x20, 0x40, 0x44, 0x3d, 0x00 , // 0x6a j
0x7f, 0x10, 0x28, 0x44, 0x00 , // 0x6b k
0x00, 0x41, 0x7f, 0x40, 0x00 , // 0x6c l
0x7c, 0x04, 0x18, 0x04, 0x78 , // 0x6d m
0x7c, 0x08, 0x04, 0x04, 0x78 , // 0x6e n
0x38, 0x44, 0x44, 0x44, 0x38 , // 0x6f o
0x7c, 0x14, 0x14, 0x14, 0x08 , // 0x70 p
0x08, 0x14, 0x14, 0x18, 0x7c , // 0x71 q
0x7c, 0x08, 0x04, 0x04, 0x08 , // 0x72 r
0x48, 0x54, 0x54, 0x54, 0x20 , // 0x73 s
0x04, 0x3f, 0x44, 0x40, 0x20 , // 0x74 t
0x3c, 0x40, 0x40, 0x20, 0x7c , // 0x75 u
0x1c, 0x20, 0x40, 0x20, 0x1c , // 0x76 v
0x3c, 0x40, 0x30, 0x40, 0x3c , // 0x77 w
0x44, 0x28, 0x10, 0x28, 0x44 , // 0x78 x
0x0c, 0x50, 0x50, 0x50, 0x3c , // 0x79 y
0x44, 0x64, 0x54, 0x4c, 0x44 , // 0x7a z
0x00, 0x08, 0x36, 0x41, 0x00 , // 0x7b {
0x00, 0x00, 0x7f, 0x00, 0x00 , // 0x7c |
0x00, 0x41, 0x36, 0x08, 0x00 , // 0x7d }
0x10, 0x08, 0x08, 0x10, 0x08 , // 0x7e ~
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x7f
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x80 A // Русские символы
0x7f, 0x49, 0x49, 0x49, 0x33 , // 0x81 Б
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x82 В
0x7f, 0x01, 0x01, 0x01, 0x03 , // 0x83 Г
0xe0, 0x51, 0x4f, 0x41, 0xff , // 0x84 Д
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x85 E
0x77, 0x08, 0x7f, 0x08, 0x77 , // 0x86 Ж
0x41, 0x49, 0x49, 0x49, 0x36 , // 0x87 З
0x7f, 0x10, 0x08, 0x04, 0x7f , // 0x88 И
0x7c, 0x21, 0x12, 0x09, 0x7c , // 0x89 Й
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x8A K
0x20, 0x41, 0x3f, 0x01, 0x7f , // 0x8B Л
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x8C M
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x8D H
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x8E O
0x7f, 0x01, 0x01, 0x01, 0x7f , // 0x8F П
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x90 P
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x91 C
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x92 T
0x47, 0x28, 0x10, 0x08, 0x07 , // 0x93 У
0x1c, 0x22, 0x7f, 0x22, 0x1c , // 0x94 Ф
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x95 X
0x7f, 0x40, 0x40, 0x40, 0xff , // 0x96 Ц
0x07, 0x08, 0x08, 0x08, 0x7f , // 0x97 Ч
0x7f, 0x40, 0x7f, 0x40, 0x7f , // 0x98 Ш
0x7f, 0x40, 0x7f, 0x40, 0xff , // 0x99 Щ
0x01, 0x7f, 0x48, 0x48, 0x30 , // 0x9A Ъ
0x7f, 0x48, 0x30, 0x00, 0x7f , // 0x9B Ы
0x00, 0x7f, 0x48, 0x48, 0x30 , // 0x9C Э
0x22, 0x41, 0x49, 0x49, 0x3e , // 0x9D Ь
0x7f, 0x08, 0x3e, 0x41, 0x3e , // 0x9E Ю
0x46, 0x29, 0x19, 0x09, 0x7f , // 0x9F Я
0x20, 0x54, 0x54, 0x54, 0x78 , // 0xA0 a
0x3c, 0x4a, 0x4a, 0x49, 0x31 , // 0xA1 б
0x7c, 0x54, 0x54, 0x54, 0x28 , // 0xA2 в
0x7c, 0x04, 0x04, 0x04, 0x0c , // 0xA3 г
0xe0, 0x54, 0x4c, 0x44, 0xfc , // 0xA4 д
0x38, 0x54, 0x54, 0x54, 0x18 , // 0xA5 e
0x6c, 0x10, 0x7c, 0x10, 0x6c , // 0xA6 ж
0x44, 0x44, 0x54, 0x54, 0x28 , // 0xA7 з
0x7c, 0x20, 0x10, 0x08, 0x7c , // 0xA8 и
0x7c, 0x41, 0x22, 0x11, 0x7c , // 0xA9 й
0x7c, 0x10, 0x10, 0x28, 0x44 , // 0xAA к
0x20, 0x44, 0x3c, 0x04, 0x7c , // 0xAB л
0x7c, 0x08, 0x10, 0x08, 0x7c , // 0xAC м
0x7c, 0x10, 0x10, 0x10, 0x7c , // 0xAD н
0x38, 0x44, 0x44, 0x44, 0x38 , // 0xAE o
0x7c, 0x04, 0x04, 0x04, 0x7c , // 0xAF п
0x7C, 0x14, 0x14, 0x14, 0x08 , // 0xB0 p
0x38, 0x44, 0x44, 0x44, 0x20 , // 0xB1 c
0x04, 0x04, 0x7c, 0x04, 0x04 , // 0xB2 т
0x0C, 0x50, 0x50, 0x50, 0x3C , // 0xB3 у
0x30, 0x48, 0xfc, 0x48, 0x30 , // 0xB4 ф
0x44, 0x28, 0x10, 0x28, 0x44 , // 0xB5 x
0x7c, 0x40, 0x40, 0x40, 0xfc , // 0xB6 ц
0x0c, 0x10, 0x10, 0x10, 0x7c , // 0xB7 ч
0x7c, 0x40, 0x7c, 0x40, 0x7c , // 0xB8 ш
0x7c, 0x40, 0x7c, 0x40, 0xfc , // 0xB9 щ
0x04, 0x7c, 0x50, 0x50, 0x20 , // 0xBA ъ
0x7c, 0x50, 0x50, 0x20, 0x7c , // 0xBB ы
0x7c, 0x50, 0x50, 0x20, 0x00 , // 0xBC ь
0x28, 0x44, 0x54, 0x54, 0x38 , // 0xBD э
0x7c, 0x10, 0x38, 0x44, 0x38 , // 0xBE ю
0x08, 0x54, 0x34, 0x14, 0x7c , // 0xBF я
};
//********************************************************
// ==== Считывание напряжения питания ардуинки (Vcc) ====
#define Vref11 1.095 // для точной подстройки результата измерений
float ReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // устанавливаем вход АЦП на VCC !!!
delay(1); // задержка для устаканивания АЦП. Можно её избежать, если ADMUX как в строке выше (не менялся)
ADCSRA |= _BV(ADSC); // запуск АЦП преобразования
while (bit_is_set(ADCSRA, ADSC)); // ждем, пока АЦП отработает (выставит бит)
return (Vref11 * 1023.0) / (ADCL | (ADCH << 8)); // результат преобразования в вольтах
}
/////// ==== Температура ==== ////////
double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000)); // 10000=10кОм Для подстройки правим 10000.
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15; // Kelvin to Celcius
return Temp;
}
void setup() {
pinMode(KEY_OK, INPUT); pinMode(KEY_L, INPUT); pinMode(KEY_R, INPUT); // настраиваем кнопки на вход
digitalWrite(KEY_OK, HIGH); digitalWrite(KEY_L, HIGH); digitalWrite(KEY_R, HIGH); // подтяжка к плюсу питания
VCC = ReadVcc();
Inicialize(); //Инициализация дисплея
Clear_LCD();
for (byte i = 0; i < 3; i++)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте
print(10, i * 10, 1, (buffer));
//delay( 500 );
}
Update();
// delay(KEY_DELAY);
while (digitalRead(KEY_OK)) { // цикл, пока не нажали кнопку ОК
Update();
// Если не нажата 10 сек кнопка ок вход в режим осцилоографа автоматом
osc--;
if (osc==0) break;
////////// Выводим показание /////////
float_print(60, 20, 1, analogRead(VBAT)*VCC/1024,1); //Вольтаж батареи
float_print(55, 40, 1, analogRead(TempC), 1); // выводим на экран показание Температуры
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[3]))); // пишем слово "Температура"
print(10, 40, 1, (buffer));
delay( 300 );
} // цикл нажатия ОК
// нажали кнопку ОК из меню, инициализируем и выходим из меню
count = 0; //countX = 0; // восстанавливаем на всякий случай переменные
if (mode == 0) FreqCount.begin(1000);
if (mode == 1) {
InitTimersSafe();
}
if (mode == 2) {
InitTimersSafe();
}
if (mode == 4 || mode == 5) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки
for (char a=37; a>0; a-=2);
}
// беcконечный цикл - по сути прыгаем в подпрограммы
void loop() {
switch (mode) {
// Прыгаем в выбранный режим из главного меню
case 0 : Oscil(); break; // "выпадаем" в осцилл
}
}
// === Читаем с АЦП данные и помещаем их в буфер === //
void ReadAdc() {
if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7)
ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4)
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
adcBuf[i] = ADCH; // записываем данные в массив
}
delay(0.3 * BUFSIZE); // компенсация задержки по сравнению с разверткой 0...
} else { // развертка с задержками (delay)
ADCSRA = 0b11100111; // делитель на /128
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
delayMicroseconds(500); // делаем задержку
adcBuf[i] = ADCH; // записываем данные в массив
}
}
}
// === Чтение цифровых данных со всего порта C (A0...A5) === //
/*void ReadDig() {
if (razv == 9) {
for (int i = 0; i < BUFSIZE; i++) adcBuf[i] = PINC; // быстро читаем данные
} else {
for (int i = 0; i < BUFSIZE; i++) {
adcBuf[i] = PINC; // читаем данные
delayMicroseconds((9 - razv) * 100);
}
}
}*/
// ==== функция вывода float ====
void float_print(byte x, byte y, boolean color, float num, byte zn) { // последняя переменная- кол знаков после запятой
char c[20];
long d = num;
byte m = 1;
while (d > 9) {
d = d / 10;
m++;
}
print(x, y, color, dtostrf(num, m, zn, c));
}
/*int GetCountsOfDigits(int n) //найти количество цифр в числе <a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>
{
return n < 10 ? 1 :
n < 100 ? 2 :
n < 1000 ? 3 :
n < 10000 ? 4 :
n < 100000 ? 5 :
n < 1000000 ? 6 :
n < 10000000 ? 7 :
n < 100000000 ? 8 :
n < 1000000000 ? 9 : 10;
}*/
// ==== найти количество цифр в числе <a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>
/*static int stringSize(long x) {
long p = 10;
for (int i = 1; i < 19; i++) {
if (x < p)
return i;
p = 10 * p;
}
return 19;
}*/
void vivod(byte x, byte y, byte n, byte k) { // //Печать цифры размером 24х48 пикселя (x, y, цифра, размер (1-24х48, 2-12х24))
if ((n != 1) && (n != 4)) {
fillRect(x + 3 / k, y, 15 / k, 5 / k, 1 ); // сегмент A
}
if ((n != 5) && (n != 6)) {
fillRect(x + 16 / k, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент B
}
if (n != 2) {
fillRect(x + 16 / k, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент C
}
if ((n != 1) && (n != 4) && (n != 7)) {
fillRect(x + 3 / k, y + 42 / k, 15 / k, 5 / k, 1 ); // сегмент D
}
if ((n == 0) || (n == 2) || (n == 6) || (n == 8)) {
fillRect(x, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент E
}
if ((n != 1) && (n != 2) && (n != 3) && (n != 7)) {
fillRect(x, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент F
}
if ((n != 0) && (n != 1) && (n != 7)) {
fillRect(x + 3 / k, y + 21 / k, 15 / k, 5 / k, 1 ); // сегмент G
}
}
//====================================================указатель меню
/*void ukazatel() {
fillRect(1, 1, 8, 60, 0);
for (byte i = 0; i < 4; i++) { // указатель меню
drawLine(1 + i, mode * 10 + i, 1 + i, mode * 10 + 6 - i, 1);
}
Update();
delay(KEY_DELAY);
}
*/
//===================================================Инициализация дисплея
void Inicialize() {
pinMode(RES, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(Data, OUTPUT);
pinMode(Clock, OUTPUT);
// Инициализация дисплея
dWrite(RES, 1);
dWrite(Clock, 0);
dWrite(Data, 0);
dWrite(CS, 0);
delay(20);
dWrite(CS, 1);
SendByte(0, 0x2F); // Power control set(charge pump on/off)
SendByte(0, 0xA4);
SendByte(0, 0xAF); // экран вкл/выкл
//Clear_LCD();
//Update();
}
//=======================================================Управление пинами
void dWrite(byte pin, byte val) {
byte bit = digitalPinToBitMask(pin);
volatile byte *out;
out = portOutputRegister(digitalPinToPort(pin));
(val) ? *out |= bit : *out &= ~bit;
}
//=========================================================Отправка 9 байт
void SendByte(byte mode, byte c) {
dWrite(CS, 0);
(mode) ? dWrite(Data, 1) : dWrite(Data, 0);
dWrite(Clock, 1);
for (byte i = 0; i < 8; i++) {
dWrite(Clock, 0);
(c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0);
dWrite(Clock, 1);
c <<= 1;
}
dWrite(Clock, 0);
}
//======================================================Очистка дисплея
void Clear_LCD() {
for (int index = 0; index < 864 ; index++) {
LCD_RAM[index] = (0x00);
}
}
//=====================================================Обновить дисплей
void Update() {
for (byte p = 0; p < 9; p++) {
SendByte(0, 0xB0 | p);
SendByte(0, 0x00);
SendByte(0, 0x10);
for (byte col = 0; col < 96; col++) {
SendByte(1, LCD_RAM[(96 * p) + col]);
}
}
}
//===================================================Нарисовать пиксель
inline __attribute__((always_inline)) void drawPixel (byte x, byte y, boolean color) {
// if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; // NAN херня
if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8);
else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8);
}
//=====================================================Нарисовать букву
void drawChar(byte x, byte y, boolean color, unsigned char c) {
if ((x >= 96) || (y >= 68) || ((x + 4) < 0) || ((y + 7) < 0)) return;
if (c < 128) c = c - 32;
if (c >= 144 && c <= 175) c = c - 48;
if (c >= 128 && c <= 143) c = c + 16;
if (c >= 176 && c <= 191) c = c - 48;
if (c > 191) return;
for (byte i = 0; i < 6; i++ ) {
byte line;
(i == 5) ? line = 0x0 : line = pgm_read_byte(font + (c * 5) + i); // line = EEPROM.read((c * 5) + i);
for (byte j = 0; j < 8; j++) {
// (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color);
if(line & 0x1)
{
drawPixel(x + i, y + j, color);
}
else
{
drawPixel(x + i, y + j, !color);
}
line >>= 1;
}
}
}
//========================================================Вывод строки
void print(byte x, byte y, boolean color, char *str) {
unsigned char type = *str;
if (type >= 128) x = x - 3;
while (*str) {
drawChar(x, y, color, *str++);
unsigned char type = *str;
(type >= 128) ? x = x + 3 : x = x + 6;
}
}
//========================================================Вывод числовых значений
void print(byte x, byte y, boolean color, long num) {
char c[20];
print(x, y, color, ltoa(num, c, 10));
}
//====================================================Рисование линии
void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) {
int steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int err = dx / 2;
int ystep;
(y0 < y1) ? ystep = 1 : ystep = -1;
for (; x0 <= x1; x0++) {
// (steep) ? drawPixel(y0, x0, color) : drawPixel(x0, y0, color);
if(steep)
{
drawPixel(y0, x0, color);
}
else
{
drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
/////////////////добавь где-то, например, под функцией DrawLine такую функцию:////////////////////////////
void drawLineUltraFast(byte x, byte y0, byte y1, boolean color) {
if(y0 > y1)
{
byte tmp = y0;
y0 = y1;
y1 = tmp;
}
while(y0 <= y1)
{
drawPixel(x, y0, color);
y0++;
}
}
//========================================Рисование вертикальной линии
void drawFastVLine(byte x, byte y, byte h, boolean color) {
drawLine(x, y, x, y + h - 1, color);
}
//======================================Рисование горизонтальной линии
void drawFastHLine(byte x, byte y, byte w, boolean color) {
drawLine(x, y, x + w - 1, y, color);
}
//=====================================Рисование залитый прямоугольник
void fillRect(byte x, byte y, byte w, byte h, boolean color) {
for (byte i = x; i < x + w; i++) {
drawFastVLine(i, y, h, color);
}
}
//=====================================Рисование битового нолика
void printnull(byte a, byte i) {
drawPixel(29 + a - i * 4, 64, 1);
drawFastVLine(28 + a - i * 4, 65, 2, 1); // и вывести биты на дисплей
drawFastVLine(30 + a - i * 4, 65, 2, 1);
drawPixel(29 + a - i * 4, 67, 1);
}
// === Осциллоскоп === //
void Oscil() {
// установка опорного напряжения АЦП и настройка входа АЦП
ADMUX = vRef ? 0b01100011 : 0b11100011;
label_ReadAdc:
// === Обработка кнопок === //
if (!digitalRead(KEY_L)) switch (menu) { // кнопка лево:)
case 0 : razv--; if (razv == 255) razv = 6; break; // меняем развертку
case 1 : grOffset -= 20; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе
}
if (!digitalRead(KEY_R)) switch (menu) { // кнопка право:)
case 0 : razv++; if (razv == 7) razv = 0; break; // меняем развертку
case 1 : grOffset += 20; if (grOffset > BUFSIZE - LCDX) grOffset = BUFSIZE - LCDX; break; // листаем график в паузе
}
if (!digitalRead(KEY_OK)) switch (++menu) {
case 1: grOffset = 0; pause = 1; break; // вход в паузу - антидребезг типа
case 2: menu = 0; pause = 0; break; // перебор меню
}
////////////////
// === Ведём рассчеты === //
if (!pause) { // если нет паузы
ReadAdc(); // то снимаем осциллограмму
// == Вычисляем максимальное и минимальное значение сигнала == //
vMax = 0; vMin = 0xFF;
for (int y = 1; y < 255; y++) {
if (vMax < adcBuf[y]) vMax = adcBuf[y]; // пока 255, но надо экспериментировать
if (vMin > adcBuf[y]) vMin = adcBuf[y];
}
vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала
// == Определение точки синхронизации == //
bool flagZero = 0; grOffset = 0; // сброс флага и точки синхронизации
// Ищем перепад от меньшего уровня к большему
for (int y = 1; y < BUFSIZE - LCDX; y++) { // смотрим весь массив данных АЦП
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг
if (flagZero && adcBuf[y] > vSync) {
grOffset = y; // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла
break;
}
}
// === Считаем частоту сигнала === //
if (vRef && vMax * VCC / 255 > 2.7) { // если можем замерить аппаратно - меряем
if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала
} else { // === Меряем частоту сигнала программно === //
flagZero = 0; count = 0; // сброс флага и счетчика
for (int y = grOffset; y < BUFSIZE - LCDX; y++) { // смотрим массив от точки синхронизации до конца
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг
if (flagZero && adcBuf[y] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период
switch (razv) { // считем частоту периода
case 6: count = 1000000 / ((y - grOffset - 1) * 3.25); break; // делитель 4
case 5: count = 1000000 / ((y - grOffset) * 3.25) / 2; break; // делитель 8
case 4: count = 1000000 / ((y - grOffset) * 3.25) / 4; break; // делитель 16
case 3: count = 1000000 / ((y - grOffset) * 3.25) / 8; break; // делитель 32
case 2: count = 1000000 / ((y - grOffset) * 3.25) / 16; break; // делитель 64
case 1: count = 1000000 / ((y - grOffset) * 3.25) / 32; break; // делитель 128
case 0: count = 1000000 / ((y - grOffset) * 510); break; // делитель 128 тоже
}
break;
}
}
}
count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы
} // закончили вести рассчеты
Clear_LCD(); // чистим экран...
// === Отрисовка меню осцилла ===
// if (vRef) TextColor = 0; else TextColor = 1;
if (vRef) float_print(0, 0, 1, VCC, 1); else {
if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "0.2");
}
if (menu == 0) TextColor = 0; else TextColor = 1; drawChar(21, 0, 1, 'р'); print(27, 0, 1, razv);
if (menu == 1) { // тут задержка для компенсации с остальными задержками
delay(100);
// print(48, 0, 0, " Pause ");
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); // необходимые функции и расшифровки, просто скопируйте
print(48, 0, 0, (buffer));
} else TextColor = 1;
if (!pause) float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты
else { // рисуем прокрутку в режиме паузы
temp = grOffset / 8;
drawFastHLine(temp, 10, 6, 1); drawFastHLine(temp, 9, 6, 1);
} // шкала прокрутки
if (vRef && vMax * VCC / 255 > 2.7) drawChar(37, 0, 1, 'А'); // если замер - "а"ппаратный
else drawChar(37, 0, 1, 'П'); // иначе "п"програмный
float_print(73, 12, 1, vMax * (vRef ? VCC : 1.1) / 255, 2); // рисуем максимальное напряжение сигнала
float_print(78, 54, 1, vMin * (vRef ? VCC : 1.1) / 255, 1); // рисуем минимальное напряжение сигнала
if (vMax==0xFF) for(int y=10; y<68; y++) drawFastHLine( 0, y, 5, 5); // превышение максимума АЦП
// == Отрисовка сетки == //
for (byte i = 11; i < 68; i = i + 14) {
drawFastHLine( 0, i, 2, 1); // черточки слева
}
for (byte i = 67; i > 10; i = i - 4) {
drawPixel(24, i, 1);
drawPixel(48, i, 1);
drawPixel(72, i, 1);
}
for (byte i = 8; i < 96; i = i + 4) {
drawPixel(i, 39, 1);
}
///////////////авто razv//////////////
if (avtorazv)
#define PER 1.3
if (count > 3823.3*PER) razv = 6; else
if (count > 1934.5*PER) razv = 5; else
if (count > 0969.3*PER) razv = 4; else
if (count > 0486.8*PER) razv = 3; else
if (count > 0245.8*PER) razv = 2; else
if (count > 0120.1*PER) razv = 1; else razv = 0;
//bulat если зашкаливает включаем предел 5 в
if (vMax==255){
if (vRef==0)
{
vRef=1;
ADMUX = 0b01100011;// выбор внутреннего опорного 5.0 В
goto label_ReadAdc;
}
}
//bulat если 5 в и уровень менее 1,1 в то вкл предел 1,1 в
if (vMax<=55){
if (vRef==1)
{
vRef=0;
ADMUX = 0b11100011;// выбор внутреннего опорного 1,1В
goto label_ReadAdc;
}
}
//bulat здесь автопредел 1,1/0,22 в,программный
kdel=5;
if (vMax<=55){
if (vRef==0)
{
kdel=1;
}
}
// == Отрисовка графика == //
for (uint8_t x = 0; x < 92; x++) drawLineUltraFast(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
// for (uint8_t x = 0; x < 92; x++) drawLine(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, x + 4, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
Update();
}
не понимаю, почему у тебя всегда что-то по другому) ты коллапсируешь квантовую волновую функцию где-то не в том месте)) проверяй целиком. жду чё как))
только что изменил, забыл добавить inline __attribute__((always_inline)) перед void drawPixel... проверяй
Учусь - учусь))). Всё норм, запускается! Теперь другое дело, повеселее! Спасибо! Можно считать проект допилен....))). Я скоро на работу до позна ухожу, буду не на связи. Видос делать?
Мой комп при загрузке скетча в синий экран смерти уходит на 10-ке (крыша едет), как я ещё выдерживаю?)))
нормально) конечно, далеко от идеала, но уже что-то) может в свободное время еще немного подпилю. ускорять еще есть куда и сильно. посмотрим. пока займусь своим цветным чёто-скопом)) надо украсить мир, а то ч/б немного утомили)
Ничего себе, неделю на форум не заглядывал, а здесь такой прогресс! progrik, я все функции повытаскивал из чужой библы, ещё и повыбрасывал лишнее, насколько хватает познаний. Просто когда мы пользуемся чужими библиотеками, то многого не замечаем, а здесь всё на виду. Отказ от проверки в drawPixel чреват последствиями, когда контроллер виснет и не реагирует ни на что до перезагрузки, я сталкивался.
Насчёт аппаратного SPI хотелось бы поподробней, как его применить для 9-битной передачи данных на STE2007 (LCD NOKIA 1202/1230)?
И ещё, можно все рекомендации за последнюю неделю форума свести пошагово в одном посте? А то информации много, сложно разобраться.
Отказ от проверки в drawPixel чреват последствиями, когда контроллер виснет и не реагирует ни на что до перезагрузки, я сталкивался.
еще раз: проверка нужна только для библиотеки, которая будет работать даже у дурачка. а если ты не будешь пытаться выводить пиксели за пределы дисплея - она абсолютно не нужна. там в сравнении проверяется byte на "меньше ноля", это БРЕД. _подумай_, какой будет результат byte x=255; while(--x >= 0); сколько проработает цикл, когда байт станет меньше ноля? (цикл вечный, байт не может принимать отрицательные значения). хватит болтать про последствия, если не понимаешь, что в коде! а там трындец полный))
_кодер_ ОБЯЗАН знать, что делает _каждая_ строка, знать каждую переменную в своем коде. в этом коде шлак засыпан песком и пылью... кода здесь нету.
прикинем, сколько времени шлется 1 байт через функцию SendByte. в ней dWrite вызывается _28_ раз на байт!!! постоянно прижимается чипселект, хотя нужно всего один раз... если она была бы пустая - все равно по 8-12 тактов за вызов, итого 28*8 = минимум 224(!) такта на один байт. и dWrite еще тормознет патамушта и там бред, из 4 строк и кучи ереси нужно всего применить маску к порту. два такта... зачем каждый раз вычислять пин, ты не помнишь куда прицепил проводок? или если не вычислять, то зависнет и перестанет реагировать?... итого получаем 300-500-700-... тактов на байт... это фиаско. это пи*дец _полный_.
аппаратный SPI - есть подозрения, что можно дослать 1 бит руками. но это не точно. я потом узнал, что он 9 бит и авр не держит его.
вот это (mode) ? dWrite(Data, 1) : dWrite(Data, 0); а надо dWrite(Data, mode); в mode уже передается 1 или 0... еще два-три такта наши. там _везде такое_!! долго расписывать... так что даже не юзая аппаратный SPI можно еще раз в 10 ускорить отрисовку. проблема в том, что это уже не поможет. разве что на паузе. остальной код тормозит. сравни видео smokok где без ускорения (на прошлой странице, в посте где он видео с кодом выложил) и с ускорением(чуть выше). при работе почти незаметно. на паузе на перемотке раза в 2,5 быстрее.. в отрисовке код уже менее кривой. но еще кривой. остальной код мне не интересен в силу его слабости. я уже писал, что это все нужно переписать так, что б ты мог себе дать ответ на вопрос про каждую строку, переменную, вызов функции, указатель, время выполнения и возможные способы ускорения. научишься так кодить и задавать себе такие вопросы и знать/находить ответы - код полетит. до этого - только боль)))
вот смотри, в моей функции drawLineUltraFast есть код
вроде все норм. НО. раз кто-то вызвал функцию рисовать линию, то по крайней мере один пиксель будет нарисован. а это значит, что _перед_ первым вызовом drawPixel _не_нужно_ ничего проверять. и получаем ускорение еще на 2 такта. мелочь, а приятно)) получаем:
do
{
drawPixel(x, y0, color);
}
while(++y0 <= y1);
вот так это работает... почти всегда есть где ускорить)
чуть позже еще гипер-ускорю вывод, что придется замедлять искусственно на перемотке))), и отпишу простыню, что было сделано... ожидайте. ваши страдания важны для нас)))
ЗЫ: сорри за грубость, но так лучше всем. кому надо - быстрее начинают соображать. кому не надо - быстрее поймут, что еще не поздно стать лучшим работником месяца в макдональдс))
progrik, спасибо за ведро ̶п̶о̶м̶о̶е̶в̶ критики, вот из-за этого начинающие ардуинщики и бросают начатое. Я не брошу, в моём возрасте в макдональдс поздно )
По поводу LCD1202 я код недавно полностью перелопатил (другое применение, там скорость нужна была), в скетче почти годовой давности этого нет. Да в пультоскопе и не особо важна скорость вывода на экран. Сейчас мне интересен другой проект, ваш опыт сильно бы помог, возможно, стОит в личке пообщаться.
progrik, спасибо за ведро ̶п̶о̶м̶о̶е̶в̶ критики, вот из-за этого начинающие ардуинщики и бросают начатое. Я не брошу, в моём возрасте в макдональдс поздно )
По поводу LCD1202 я код недавно полностью перелопатил (другое применение, там скорость нужна была), в скетче почти годовой давности этого нет. Да в пультоскопе и не особо важна скорость вывода на экран. Сейчас мне интересен другой проект, ваш опыт сильно бы помог, возможно, стОит в личке пообщаться.
Не ошибается тот,кто ничего не делает.Сделать выводы и добивать дальше..Не отступать и не сдаваться..
progrik, спасибо за ведро ̶п̶о̶м̶о̶е̶в̶ критики, вот из-за этого начинающие ардуинщики и бросают начатое. Я не брошу, в моём возрасте в макдональдс поздно )
ну вообще-то по ходу наполнения ведра я, в отличии от многих, разжевывал каждый свой шаг, чужие ошибки, и пытался максимально донести, что как, зачем и почему, и приводил код... так что, в одной руке ведро из под помоев (помои уже известно где), а в другой намыленная мочалка... а если кто не хочет отмыться, то в макдональдс никогда не поздно))
скорость важна и нужна. не неси ересь. с таким кодом даже кнопки хер во время нажимаются, ведь так? а быстрые процессы/всплески, да мало ли чего посмотреть? слайд-шоу в 3 к/с - это херня даже для часов. неужели ты не видел Okmor по моему сделал на внешнем ацп - он тоже разогнал код вывода, так приятно смотреть, хоть и унылое ч/б...
лички тут нет. заводи топик, тебе помогут... может на странице 87-й )) по крайней мере столько страниц было нужно, чтоб я не выдержал и влез разогнать унылое уныние...
короче мне все ясно. одному говорю: -а чего у тебя часы моргают полтора раза в секунду, как попало, вообще не во время и с разными интервалами, в лупе идет постоянный опрос RTC, ведь на модуле есть нога, которая изменяет состояние два раза в секунду(меандр 1 Гц), просто подключи ее на прерывание и рисуй точки ровно прировно раз в пол сек - вкл/выкл и там уже раз в минуту/час/сутки дергай модуль RTC. его ответ был ох*енен: -я это сделал для примера, каждый сам сможет подправить и сделать что захочет.
ВЫ СЕРЬЕЗНО? одному скорость отрисовки в осциллографе не нужна, другой кидает на стол провода, ардуино нано, дисплей, модули, смешал в кучу и говорит - вот что я сделал для вас. это просто демка. вы теперь сможете сделать все сами...
короче, я убеждаюсь, что шапокляк была права. у тебя же говоришь есть гиперскоростной вывод, а тут у человека нет. я все таки допилю исключительно вывод, раз взялся. а дальше - гори оно огнем. раз все уже хорошо.
Да я не обижаюсь, всё-таки когда говорят "ты дурак тут, тут и вот тут" и объясняют причину, то это всё же лучше, чем просто "ты дурак". За подсказки спасибо, приму к сведению, хотя к проекту пультоскопа пока не вернусь, сейчас другие приоритеты. А чтобы показать мой суперскоростной вывод, его нужно привести в соответствие с этим проектом, а на это руки не доходят, потому и не показываю, уж извините. Да и забросают помидорами за "трындец полный".
я заморочился, глянул время исполнения - не так как хотелось. поэтому еще допилил вывод, теперь работает еще приблизительно раз в 5 быстрее. сто кадров выводятся за 2+- сек (было около 9-10сек), зависит от заполнения. 100 кадров с ровным лучем за 1,3 сек. то есть, +-50 FPS получается. теперь общая скорость больше будет зависеть от остального кода.
я думал раз в 10 скорость поднимется. но благодаря оптимизатору компилятора этот код хоть как-то работал. браво оптимизаторы компилятора!!)) я убрал ну просто нереальное кол-во вызовов функций - но ускорилось не в 10, а только в 5 раз. ну 5 так 5)) я бы и на аппаратный SPI всю эту хрень повесил, но не имеет смысла, пока есть остальной код...))
чтобы поднять fps "живого" отображения на низких скоростях adc, синхронизацию нужно ловить прямо в функции чтения ацп, и читать буфер до размера дисплея по Х, или чуть больше. а на всю длину буфера читать только по нажатии на паузу. не нужно постоянно считывать килобайт, если ты видишь только 90 байт... разве что немного упадет точность определения частоты...
UPD: вот код.seri0shka вместо простыни все изменения я пометил в комментариях как "progrik". вывод теперь должен херачить как паровоз! если что не понятно - спрашивай
#define BUFSIZE 800
#define history 50
volatile int cur_index = 0; //переменная для отсчета замеров
volatile int StartIndex = 0; // номер замера с которого нужно выводить результат (считается так: (замер сработки триггера-предистория))
volatile byte prev_data; // предыдущее состояние шины
volatile byte pattern_mask; // маска для события PATTERN
volatile byte pattern_value; // ЗНАЧЕНИЕ состояния для события PATTERN
volatile boolean trigger_event = false; //признак сработки триггера
volatile int time_disc = 0; // время выборки 1-го значения
unsigned long prevMillis, curMillis;
enum triggerEvents {BURST, MASTER_RISE, MASTER_FALL, PATTERN}; //именнованный список триггеров-событий
bool flag = 0;
// Пины экранчика
#define RES 3
#define CS 4
#define Data 6
#define Clock 7
#define swap(a, b) { byte t = a; a = b; b = t; } //progrik: было int t... работа идет только с byte. так быстрее.
//progrik: порт(ы) для clock, data, reset, chipSelect (CS) согласно распиновке Arduino Nano пины 3,4,6,7 все на порту D
#define CLOCK_PORT PORTD
#define DATA_PORT PORTD
#define RESET_PORT PORTD
#define CS_PORT PORTD
//progrik: маски для порта вывода. для Clock указан пин 7
//progrik: в распиновке Arduino NANO это D7 - порт D пин 7, маска - B10000000. для D0 была бы B00000001 (счет с ноля справа налево)
#define CLOCK_MASK B10000000
#define DATA_MASK B01000000
#define RESET_MASK B00001000
#define CS_MASK B00010000
//progrik: определяем макросы для действий с управляющими пинами
#define CLOCK_ACTIVE CLOCK_PORT &= ~CLOCK_MASK
#define CLOCK_IDLE CLOCK_PORT |= CLOCK_MASK
#define DATA_ACTIVE DATA_PORT &= ~DATA_MASK
#define DATA_IDLE DATA_PORT |= DATA_MASK
#define RESET_ACTIVE RESET_PORT &= ~RESET_MASK
#define RESET_IDLE RESET_PORT |= RESET_MASK
#define CS_ACTIVE CS_PORT &= ~CS_MASK
#define CS_IDLE CS_PORT |= CS_MASK
#include <FreqCount.h>
#include <math.h>
#include <PWM.h>
// Настройки пользователя - можно менять
#define OVERCLOCK 16 // частота на которой работает Ардуино
float VCC = 5.0; // напряжение питания
#define KEY_L 11 // кнопка ЛЕВО (можно любой пин)
#define KEY_OK 12 // кнопка ОК (можно любой пин)
#define KEY_R 13 // кнопка ПРАВО (можно любой пин)
#define VBAT A1 // любой свободный аналоговый пин для измерения напряжения АКБ
#define TempC A0 // любой свободный аналоговый пин для измерения температуры
#define KEY_DELAY 200
#define LCDX 96
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "ОСЦИЛЛОГРАФ"; // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его
const char string_1[] PROGMEM = " ";
const char string_2[] PROGMEM = "VБат.= ";
const char string_3[] PROGMEM = "Temп.= ";
const char string_4[] PROGMEM = " Pause ";
// Теперь создаем таблицу с отсылками к этим строкам:
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4};
char buffer[11]; // массив должен быть достаточно велик, чтобы вместить даже самую большую строку
byte mode = 0; // пункт главного меню
byte menu = 0; // пункт меню
byte adcBuf[BUFSIZE];
byte vSync = 0; // уровень синхронизации
bool vRef = 1; // флаг опорного напряжения
bool pause = 0; // флаг режима паузы
bool avtorazv=1; // Автоматический выбор развертки
byte TextColor = 1;
byte razv = 0;
byte trig = 0;
int kdel=5; //bulat автопредел 1,1/0,22 вольта
int osc=50; // авто вкл. режима осциллографа (секунды)
int grOffset = 0; // смещение графика в рабочем режиме
byte vMax, vMin; // максимальное и минимальное напряжение сигнала
int temp = 0; // временная переменная***
unsigned long count = 1;
byte LCD_RAM[96 * 9]; // 96 * 9
static const char font[] PROGMEM = {
//HEX B DEC переводим
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x20 space
0x00, 0x00, 0x5f, 0x00, 0x00 , // 0x21 !
0x00, 0x07, 0x00, 0x07, 0x00 , // 0x22 "
0x14, 0x7f, 0x14, 0x7f, 0x14 , // 0x23 #
0x24, 0x2a, 0x7f, 0x2a, 0x12 , // 0x24 $
0x23, 0x13, 0x08, 0x64, 0x62 , // 0x25 %
0x36, 0x49, 0x55, 0x22, 0x50 , // 0x26 &
0x00, 0x05, 0x03, 0x00, 0x00 , // 0x27 '
0x00, 0x1c, 0x22, 0x41, 0x00 , // 0x28 (
0x00, 0x41, 0x22, 0x1c, 0x00 , // 0x29 )
0x14, 0x08, 0x3e, 0x08, 0x14 , // 0x2a *
0x08, 0x08, 0x3e, 0x08, 0x08 , // 0x2b +
0x00, 0x50, 0x30, 0x00, 0x00 , // 0x2c ,
0x08, 0x08, 0x08, 0x08, 0x08 , // 0x2d -
0x00, 0x60, 0x60, 0x00, 0x00 , // 0x2e .
0x20, 0x10, 0x08, 0x04, 0x02 , // 0x2f /
0x3e, 0x51, 0x49, 0x45, 0x3e , // 0x30 0
0x00, 0x42, 0x7f, 0x40, 0x00 , // 0x31 1
0x42, 0x61, 0x51, 0x49, 0x46 , // 0x32 2
0x21, 0x41, 0x45, 0x4b, 0x31 , // 0x33 3
0x18, 0x14, 0x12, 0x7f, 0x10 , // 0x34 4
0x27, 0x45, 0x45, 0x45, 0x39 , // 0x35 5
0x3c, 0x4a, 0x49, 0x49, 0x30 , // 0x36 6
0x01, 0x71, 0x09, 0x05, 0x03 , // 0x37 7
0x36, 0x49, 0x49, 0x49, 0x36 , // 0x38 8
0x06, 0x49, 0x49, 0x29, 0x1e , // 0x39 9
0x00, 0x36, 0x36, 0x00, 0x00 , // 0x3a :
0x00, 0x56, 0x36, 0x00, 0x00 , // 0x3b ;
0x08, 0x14, 0x22, 0x41, 0x00 , // 0x3c <
0x14, 0x14, 0x14, 0x14, 0x14 , // 0x3d =
0x00, 0x41, 0x22, 0x14, 0x08 , // 0x3e >
0x02, 0x01, 0x51, 0x09, 0x06 , // 0x3f ?
0x32, 0x49, 0x79, 0x41, 0x3e , // 0x40 @
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x41 A
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x42 B
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x43 C
0x7f, 0x41, 0x41, 0x22, 0x1c , // 0x44 D
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x45 E
0x7f, 0x09, 0x09, 0x09, 0x01 , // 0x46 F
0x3e, 0x41, 0x49, 0x49, 0x7a , // 0x47 G
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x48 H
0x00, 0x41, 0x7f, 0x41, 0x00 , // 0x49 I
0x20, 0x40, 0x41, 0x3f, 0x01 , // 0x4a J
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x4b K
0x7f, 0x40, 0x40, 0x40, 0x40 , // 0x4c L
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x4d M
0x7f, 0x04, 0x08, 0x10, 0x7f , // 0x4e N
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x4f O
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x50 P
0x3e, 0x41, 0x51, 0x21, 0x5e , // 0x51 Q
0x7f, 0x09, 0x19, 0x29, 0x46 , // 0x52 R
0x46, 0x49, 0x49, 0x49, 0x31 , // 0x53 S
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x54 T
0x3f, 0x40, 0x40, 0x40, 0x3f , // 0x55 U
0x1f, 0x20, 0x40, 0x20, 0x1f , // 0x56 V
0x3f, 0x40, 0x38, 0x40, 0x3f , // 0x57 W
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x58 X
0x07, 0x08, 0x70, 0x08, 0x07 , // 0x59 Y
0x61, 0x51, 0x49, 0x45, 0x43 , // 0x5a Z
0x00, 0x7f, 0x41, 0x41, 0x00 , // 0x5b [
0x02, 0x04, 0x08, 0x10, 0x20 , // 0x5c backslash
0x00, 0x41, 0x41, 0x7f, 0x00 , // 0x5d ]
0x04, 0x02, 0x01, 0x02, 0x04 , // 0x5e ^
0x40, 0x40, 0x40, 0x40, 0x40 , // 0x5f _
0x00, 0x01, 0x02, 0x04, 0x00 , // 0x60 `
0x20, 0x54, 0x54, 0x54, 0x78 , // 0x61 a
0x7f, 0x48, 0x44, 0x44, 0x38 , // 0x62 b
0x38, 0x44, 0x44, 0x44, 0x20 , // 0x63 c
0x38, 0x44, 0x44, 0x48, 0x7f , // 0x64 d
0x38, 0x54, 0x54, 0x54, 0x18 , // 0x65 e
0x08, 0x7e, 0x09, 0x01, 0x02 , // 0x66 f
0x0c, 0x52, 0x52, 0x52, 0x3e , // 0x67 g
0x7f, 0x08, 0x04, 0x04, 0x78 , // 0x68 h
0x00, 0x44, 0x7d, 0x40, 0x00 , // 0x69 i
0x20, 0x40, 0x44, 0x3d, 0x00 , // 0x6a j
0x7f, 0x10, 0x28, 0x44, 0x00 , // 0x6b k
0x00, 0x41, 0x7f, 0x40, 0x00 , // 0x6c l
0x7c, 0x04, 0x18, 0x04, 0x78 , // 0x6d m
0x7c, 0x08, 0x04, 0x04, 0x78 , // 0x6e n
0x38, 0x44, 0x44, 0x44, 0x38 , // 0x6f o
0x7c, 0x14, 0x14, 0x14, 0x08 , // 0x70 p
0x08, 0x14, 0x14, 0x18, 0x7c , // 0x71 q
0x7c, 0x08, 0x04, 0x04, 0x08 , // 0x72 r
0x48, 0x54, 0x54, 0x54, 0x20 , // 0x73 s
0x04, 0x3f, 0x44, 0x40, 0x20 , // 0x74 t
0x3c, 0x40, 0x40, 0x20, 0x7c , // 0x75 u
0x1c, 0x20, 0x40, 0x20, 0x1c , // 0x76 v
0x3c, 0x40, 0x30, 0x40, 0x3c , // 0x77 w
0x44, 0x28, 0x10, 0x28, 0x44 , // 0x78 x
0x0c, 0x50, 0x50, 0x50, 0x3c , // 0x79 y
0x44, 0x64, 0x54, 0x4c, 0x44 , // 0x7a z
0x00, 0x08, 0x36, 0x41, 0x00 , // 0x7b {
0x00, 0x00, 0x7f, 0x00, 0x00 , // 0x7c |
0x00, 0x41, 0x36, 0x08, 0x00 , // 0x7d }
0x10, 0x08, 0x08, 0x10, 0x08 , // 0x7e ~
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x7f
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x80 A // Русские символы
0x7f, 0x49, 0x49, 0x49, 0x33 , // 0x81 Б
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x82 В
0x7f, 0x01, 0x01, 0x01, 0x03 , // 0x83 Г
0xe0, 0x51, 0x4f, 0x41, 0xff , // 0x84 Д
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x85 E
0x77, 0x08, 0x7f, 0x08, 0x77 , // 0x86 Ж
0x41, 0x49, 0x49, 0x49, 0x36 , // 0x87 З
0x7f, 0x10, 0x08, 0x04, 0x7f , // 0x88 И
0x7c, 0x21, 0x12, 0x09, 0x7c , // 0x89 Й
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x8A K
0x20, 0x41, 0x3f, 0x01, 0x7f , // 0x8B Л
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x8C M
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x8D H
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x8E O
0x7f, 0x01, 0x01, 0x01, 0x7f , // 0x8F П
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x90 P
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x91 C
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x92 T
0x47, 0x28, 0x10, 0x08, 0x07 , // 0x93 У
0x1c, 0x22, 0x7f, 0x22, 0x1c , // 0x94 Ф
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x95 X
0x7f, 0x40, 0x40, 0x40, 0xff , // 0x96 Ц
0x07, 0x08, 0x08, 0x08, 0x7f , // 0x97 Ч
0x7f, 0x40, 0x7f, 0x40, 0x7f , // 0x98 Ш
0x7f, 0x40, 0x7f, 0x40, 0xff , // 0x99 Щ
0x01, 0x7f, 0x48, 0x48, 0x30 , // 0x9A Ъ
0x7f, 0x48, 0x30, 0x00, 0x7f , // 0x9B Ы
0x00, 0x7f, 0x48, 0x48, 0x30 , // 0x9C Э
0x22, 0x41, 0x49, 0x49, 0x3e , // 0x9D Ь
0x7f, 0x08, 0x3e, 0x41, 0x3e , // 0x9E Ю
0x46, 0x29, 0x19, 0x09, 0x7f , // 0x9F Я
0x20, 0x54, 0x54, 0x54, 0x78 , // 0xA0 a
0x3c, 0x4a, 0x4a, 0x49, 0x31 , // 0xA1 б
0x7c, 0x54, 0x54, 0x54, 0x28 , // 0xA2 в
0x7c, 0x04, 0x04, 0x04, 0x0c , // 0xA3 г
0xe0, 0x54, 0x4c, 0x44, 0xfc , // 0xA4 д
0x38, 0x54, 0x54, 0x54, 0x18 , // 0xA5 e
0x6c, 0x10, 0x7c, 0x10, 0x6c , // 0xA6 ж
0x44, 0x44, 0x54, 0x54, 0x28 , // 0xA7 з
0x7c, 0x20, 0x10, 0x08, 0x7c , // 0xA8 и
0x7c, 0x41, 0x22, 0x11, 0x7c , // 0xA9 й
0x7c, 0x10, 0x10, 0x28, 0x44 , // 0xAA к
0x20, 0x44, 0x3c, 0x04, 0x7c , // 0xAB л
0x7c, 0x08, 0x10, 0x08, 0x7c , // 0xAC м
0x7c, 0x10, 0x10, 0x10, 0x7c , // 0xAD н
0x38, 0x44, 0x44, 0x44, 0x38 , // 0xAE o
0x7c, 0x04, 0x04, 0x04, 0x7c , // 0xAF п
0x7C, 0x14, 0x14, 0x14, 0x08 , // 0xB0 p
0x38, 0x44, 0x44, 0x44, 0x20 , // 0xB1 c
0x04, 0x04, 0x7c, 0x04, 0x04 , // 0xB2 т
0x0C, 0x50, 0x50, 0x50, 0x3C , // 0xB3 у
0x30, 0x48, 0xfc, 0x48, 0x30 , // 0xB4 ф
0x44, 0x28, 0x10, 0x28, 0x44 , // 0xB5 x
0x7c, 0x40, 0x40, 0x40, 0xfc , // 0xB6 ц
0x0c, 0x10, 0x10, 0x10, 0x7c , // 0xB7 ч
0x7c, 0x40, 0x7c, 0x40, 0x7c , // 0xB8 ш
0x7c, 0x40, 0x7c, 0x40, 0xfc , // 0xB9 щ
0x04, 0x7c, 0x50, 0x50, 0x20 , // 0xBA ъ
0x7c, 0x50, 0x50, 0x20, 0x7c , // 0xBB ы
0x7c, 0x50, 0x50, 0x20, 0x00 , // 0xBC ь
0x28, 0x44, 0x54, 0x54, 0x38 , // 0xBD э
0x7c, 0x10, 0x38, 0x44, 0x38 , // 0xBE ю
0x08, 0x54, 0x34, 0x14, 0x7c , // 0xBF я
};
//********************************************************
// ==== Считывание напряжения питания ардуинки (Vcc) ====
#define Vref11 1.095 // для точной подстройки результата измерений
float ReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // устанавливаем вход АЦП на VCC !!!
delay(1); // задержка для устаканивания АЦП. Можно её избежать, если ADMUX как в строке выше (не менялся)
ADCSRA |= _BV(ADSC); // запуск АЦП преобразования
while (bit_is_set(ADCSRA, ADSC)); // ждем, пока АЦП отработает (выставит бит)
return (Vref11 * 1023.0) / (ADCL | (ADCH << 8)); // результат преобразования в вольтах
}
/////// ==== Температура ==== ////////
double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000)); // 10000=10кОм Для подстройки правим 10000.
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15; // Kelvin to Celcius
return Temp;
}
void setup() {
pinMode(KEY_OK, INPUT); pinMode(KEY_L, INPUT); pinMode(KEY_R, INPUT); // настраиваем кнопки на вход
digitalWrite(KEY_OK, HIGH); digitalWrite(KEY_L, HIGH); digitalWrite(KEY_R, HIGH); // подтяжка к плюсу питания
VCC = ReadVcc();
Inicialize(); //Инициализация дисплея
Clear_LCD();
for (byte i = 0; i < 3; i++)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте
print(10, i * 10, 1, (buffer));
//delay( 500 );
}
Update();
// delay(KEY_DELAY);
while (digitalRead(KEY_OK)) { // цикл, пока не нажали кнопку ОК
Update();
// Если не нажата 10 сек кнопка ок вход в режим осцилоографа автоматом
osc--;
if (osc==0) break;
////////// Выводим показание /////////
float_print(60, 20, 1, analogRead(VBAT)*VCC/1024,1); //Вольтаж батареи
float_print(55, 40, 1, analogRead(TempC), 1); // выводим на экран показание Температуры
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[3]))); // пишем слово "Температура"
print(10, 40, 1, (buffer));
delay( 300 );
} // цикл нажатия ОК
// нажали кнопку ОК из меню, инициализируем и выходим из меню
count = 0; //countX = 0; // восстанавливаем на всякий случай переменные
if (mode == 0) FreqCount.begin(1000);
if (mode == 1) {
InitTimersSafe();
}
if (mode == 2) {
InitTimersSafe();
}
if (mode == 4 || mode == 5) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки
for (char a=37; a>0; a-=2);
}
// беcконечный цикл - по сути прыгаем в подпрограммы
void loop() {
switch (mode) {
// Прыгаем в выбранный режим из главного меню
case 0 : Oscil(); break; // "выпадаем" в осцилл
}
}
// === Читаем с АЦП данные и помещаем их в буфер === //
void ReadAdc() {
if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7)
ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4)
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
adcBuf[i] = ADCH; // записываем данные в массив
}
delay(0.3 * BUFSIZE); // компенсация задержки по сравнению с разверткой 0...
} else { // развертка с задержками (delay)
ADCSRA = 0b11100111; // делитель на /128
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
delayMicroseconds(500); // делаем задержку
adcBuf[i] = ADCH; // записываем данные в массив
}
}
}
// === Чтение цифровых данных со всего порта C (A0...A5) === //
/*void ReadDig() {
if (razv == 9) {
for (int i = 0; i < BUFSIZE; i++) adcBuf[i] = PINC; // быстро читаем данные
} else {
for (int i = 0; i < BUFSIZE; i++) {
adcBuf[i] = PINC; // читаем данные
delayMicroseconds((9 - razv) * 100);
}
}
}*/
// ==== функция вывода float ====
void float_print(byte x, byte y, boolean color, float num, byte zn) { // последняя переменная- кол знаков после запятой
char c[20];
long d = num;
byte m = 1;
while (d > 9) {
d = d / 10;
m++;
}
print(x, y, color, dtostrf(num, m, zn, c));
}
/*int GetCountsOfDigits(int n) //найти количество цифр в числе <a href="<a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a></a>
{
return n < 10 ? 1 :
n < 100 ? 2 :
n < 1000 ? 3 :
n < 10000 ? 4 :
n < 100000 ? 5 :
n < 1000000 ? 6 :
n < 10000000 ? 7 :
n < 100000000 ? 8 :
n < 1000000000 ? 9 : 10;
}*/
// ==== найти количество цифр в числе <a href="<a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a></a>
/*static int stringSize(long x) {
long p = 10;
for (int i = 1; i < 19; i++) {
if (x < p)
return i;
p = 10 * p;
}
return 19;
}*/
void vivod(byte x, byte y, byte n, byte k) { // //Печать цифры размером 24х48 пикселя (x, y, цифра, размер (1-24х48, 2-12х24))
if ((n != 1) && (n != 4)) {
fillRect(x + 3 / k, y, 15 / k, 5 / k, 1 ); // сегмент A
}
if ((n != 5) && (n != 6)) {
fillRect(x + 16 / k, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент B
}
if (n != 2) {
fillRect(x + 16 / k, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент C
}
if ((n != 1) && (n != 4) && (n != 7)) {
fillRect(x + 3 / k, y + 42 / k, 15 / k, 5 / k, 1 ); // сегмент D
}
if ((n == 0) || (n == 2) || (n == 6) || (n == 8)) {
fillRect(x, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент E
}
if ((n != 1) && (n != 2) && (n != 3) && (n != 7)) {
fillRect(x, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент F
}
if ((n != 0) && (n != 1) && (n != 7)) {
fillRect(x + 3 / k, y + 21 / k, 15 / k, 5 / k, 1 ); // сегмент G
}
}
//====================================================указатель меню
/*void ukazatel() {
fillRect(1, 1, 8, 60, 0);
for (byte i = 0; i < 4; i++) { // указатель меню
drawLine(1 + i, mode * 10 + i, 1 + i, mode * 10 + 6 - i, 1);
}
Update();
delay(KEY_DELAY);
}
*/
//===================================================Инициализация дисплея
void Inicialize() {
pinMode(RES, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(Data, OUTPUT);
pinMode(Clock, OUTPUT);
// Инициализация дисплея
//dWrite(RES, 1);
RESET_ACTIVE;
//dWrite(Clock, 0);
CLOCK_IDLE;
//dWrite(Data, 0);
DATA_IDLE;
//dWrite(CS, 0);
CS_IDLE;
delay(20);
//dWrite(CS, 1);
CS_ACTIVE;
SendByte(0, 0x2F); // Power control set(charge pump on/off)
SendByte(0, 0xA4);
SendByte(0, 0xAF); // экран вкл/выкл
//Clear_LCD();
//Update();
CS_IDLE; //progrik: перенес сюда из функции SendByte
}
/*
//=======================================================Управление пинами
//progrik: добалено определение inline. функция встраивается в код и не расходуется воемя на ее вызов.
//progrik: UPD: функция не испольуется, удалить.
inline __attribute__((always_inline)) void dWrite(byte pin, byte val) {
byte bit = digitalPinToBitMask(pin);
volatile byte *out;
out = portOutputRegister(digitalPinToPort(pin));
(val) ? *out |= bit : *out &= ~bit;
}
*/
//=========================================================Отправка 9 байт
//progrik: добалено определение inline. функция встраивается в код и не расходуется время на ее вызов.
//progrik: вместо многократных вызовов функций дергаем ногами при помощи написанных вверху кода макросов
inline __attribute__((always_inline)) void SendByte(byte mode, byte c) {
//dWrite(CS, 0); //progrik: чип селект нужно включить один раз в конце инициализации дисплея, и больше не трогать. перенес в инициализацию
//(mode) ? dWrite(Data, 1) : dWrite(Data, 0);
(mode) ? DATA_ACTIVE : DATA_IDLE;
//dWrite(Clock, 1);
CLOCK_ACTIVE;
for (byte i = 0; i < 8; i++)
{
//dWrite(Clock, 0);
CLOCK_IDLE;
//(c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0);
(c & 0x80) ? DATA_ACTIVE : DATA_IDLE;
//dWrite(Clock, 1);
CLOCK_ACTIVE;
c <<= 1;
}
//dWrite(Clock, 0);
CLOCK_IDLE;
}
//======================================================Очистка дисплея
void Clear_LCD() {
memset(LCD_RAM, 0, 864); //progrik: велосипед не нужен. memset даже чутка быстрее. это из Си.
/*
for (int index = 0; index < 864 ; index++) {
LCD_RAM[index] = (0x00);
}*/
}
//=====================================================Обновить дисплей
void Update() {
for (byte p = 0; p < 9; p++) {
SendByte(0, 0xB0 | p);
SendByte(0, 0x00);
SendByte(0, 0x10);
for (byte col = 0; col < 96; col++) {
SendByte(1, LCD_RAM[(96 * p) + col]);
}
}
}
//===================================================Нарисовать пиксель
//progrik: добалено определение inline. функция встраивается в код и не расходуется время на ее вызов.
//убрана ненужная проверка byte на "меньше ноля" и на вылет за пределы дисплея. не нужно этого допускать в коде.
inline __attribute__((always_inline)) void drawPixel(byte x, byte y, bool color) {
if(color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8);
else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8);
}
//=====================================================Нарисовать букву
void drawChar(byte x, byte y, boolean color, unsigned char c) {
if ((x >= 96) || (y >= 68) || ((x + 4) < 0) || ((y + 7) < 0)) return;
if (c < 128) c = c - 32;
if (c >= 144 && c <= 175) c = c - 48;
if (c >= 128 && c <= 143) c = c + 16;
if (c >= 176 && c <= 191) c = c - 48;
if (c > 191) return;
for (byte i = 0; i < 6; i++ ) {
byte line;
(i == 5) ? line = 0x0 : line = pgm_read_byte(font + (c * 5) + i); // line = EEPROM.read((c * 5) + i);
for (byte j = 0; j < 8; j++) {
// (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color);
if(line & 0x1)
{
drawPixel(x + i, y + j, color);
}
else
{
drawPixel(x + i, y + j, !color);
}
line >>= 1;
}
}
}
//========================================================Вывод строки
void print(byte x, byte y, boolean color, char *str) {
unsigned char type = *str;
if (type >= 128) x = x - 3;
while (*str) {
drawChar(x, y, color, *str++);
unsigned char type = *str;
(type >= 128) ? x = x + 3 : x = x + 6;
}
}
//========================================================Вывод числовых значений
void print(byte x, byte y, boolean color, long num) {
char c[20];
print(x, y, color, ltoa(num, c, 10));
}
//====================================================Рисование линии
void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) {
int steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int err = dx / 2;
int ystep;
(y0 < y1) ? ystep = 1 : ystep = -1;
for (; x0 <= x1; x0++) {
// (steep) ? drawPixel(y0, x0, color) : drawPixel(x0, y0, color);
if(steep)
{
drawPixel(y0, x0, color);
}
else
{
drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
//progrik: добавил функцию для быстрой отрисовки вертикальных линий луча
inline __attribute__((always_inline)) void drawVLineUltraFast(byte x, byte y0, byte y1, boolean color) {
if(y0 > y1)
swap(y0, y1);
do
{
drawPixel(x, y0, color);
}
while(++y0 <= y1);
}
//========================================Рисование вертикальной линии
void drawFastVLine(byte x, byte y, byte h, boolean color) {
byte y1 = y + h - 1;
do
{
drawPixel(x, y, color);
}
while(++y <= y1);
}
//======================================Рисование горизонтальной линии
//progrik: переписал...
void drawFastHLine(byte x, byte y, byte w, boolean color) {
//drawLine(x, y, x + w - 1, y, color); //жутко медленно
byte x1 = x + w - 1;
do
{
drawPixel(x, y, color);
}
while(++x <= x1);
}
//=====================================Рисование залитый прямоугольник
void fillRect(byte x, byte y, byte w, byte h, bool color) {
for(byte i = x; i < x + w; i++) {
//drawFastVLine(i, y, h, color); //progrik: это было медленно
drawVLineUltraFast(x, y, y + h - 1, color);
}
}
//=====================================Рисование битового нолика
void printnull(byte a, byte i) {
drawPixel(29 + a - i * 4, 64, 1);
drawFastVLine(28 + a - i * 4, 65, 2, 1); // и вывести биты на дисплей
drawFastVLine(30 + a - i * 4, 65, 2, 1);
drawPixel(29 + a - i * 4, 67, 1);
}
// === Осциллоскоп === //
void Oscil() {
// установка опорного напряжения АЦП и настройка входа АЦП
ADMUX = vRef ? 0b01100011 : 0b11100011;
label_ReadAdc:
// === Обработка кнопок === //
if (!digitalRead(KEY_L)) switch (menu) { // кнопка лево:)
case 0 : razv--; if (razv == 255) razv = 6; break; // меняем развертку
case 1 : grOffset -= 20; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе
}
if (!digitalRead(KEY_R)) switch (menu) { // кнопка право:)
case 0 : razv++; if (razv == 7) razv = 0; break; // меняем развертку
case 1 : grOffset += 20; if (grOffset > BUFSIZE - LCDX) grOffset = BUFSIZE - LCDX; break; // листаем график в паузе
}
if (!digitalRead(KEY_OK)) switch (++menu) {
case 1: grOffset = 0; pause = 1; break; // вход в паузу - антидребезг типа
case 2: menu = 0; pause = 0; break; // перебор меню
}
////////////////
// === Ведём рассчеты === //
if (!pause) { // если нет паузы
ReadAdc(); // то снимаем осциллограмму
// == Вычисляем максимальное и минимальное значение сигнала == //
vMax = 0; vMin = 0xFF;
for (int y = 1; y < 255; y++) {
if (vMax < adcBuf[y]) vMax = adcBuf[y]; // пока 255, но надо экспериментировать
if (vMin > adcBuf[y]) vMin = adcBuf[y];
}
vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала
// == Определение точки синхронизации == //
bool flagZero = 0; grOffset = 0; // сброс флага и точки синхронизации
// Ищем перепад от меньшего уровня к большему
for (int y = 1; y < BUFSIZE - LCDX; y++) { // смотрим весь массив данных АЦП
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг
if (flagZero && adcBuf[y] > vSync) {
grOffset = y; // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла
break;
}
}
// === Считаем частоту сигнала === //
if (vRef && vMax * VCC / 255 > 2.7) { // если можем замерить аппаратно - меряем
// if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала
} else { // === Меряем частоту сигнала программно === //
flagZero = 0; count = 0; // сброс флага и счетчика
for (int y = grOffset; y < BUFSIZE - LCDX; y++) { // смотрим массив от точки синхронизации до конца
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг
if (flagZero && adcBuf[y] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период
switch (razv) { // считем частоту периода
case 6: count = 1000000 / ((y - grOffset - 1) * 3.25); break; // делитель 4
case 5: count = 1000000 / ((y - grOffset) * 3.25) / 2; break; // делитель 8
case 4: count = 1000000 / ((y - grOffset) * 3.25) / 4; break; // делитель 16
case 3: count = 1000000 / ((y - grOffset) * 3.25) / 8; break; // делитель 32
case 2: count = 1000000 / ((y - grOffset) * 3.25) / 16; break; // делитель 64
case 1: count = 1000000 / ((y - grOffset) * 3.25) / 32; break; // делитель 128
case 0: count = 1000000 / ((y - grOffset) * 510); break; // делитель 128 тоже
}
break;
}
}
}
count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы
} // закончили вести рассчеты
Clear_LCD(); // чистим экран...
// === Отрисовка меню осцилла ===
// if (vRef) TextColor = 0; else TextColor = 1;
if (vRef) float_print(0, 0, 1, VCC, 1); else {
if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "0.2");
}
if (menu == 0) TextColor = 0; else TextColor = 1; drawChar(21, 0, 1, 'р'); print(27, 0, 1, razv);
if (menu == 1) { // тут задержка для компенсации с остальными задержками
delay(100);
// print(48, 0, 0, " Pause ");
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); // необходимые функции и расшифровки, просто скопируйте
print(48, 0, 0, (buffer));
} else TextColor = 1;
if (!pause) float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты
else { // рисуем прокрутку в режиме паузы
temp = grOffset / 8;
drawFastHLine(temp, 10, 6, 1); drawFastHLine(temp, 9, 6, 1);
} // шкала прокрутки
if (vRef && vMax * VCC / 255 > 2.7) drawChar(37, 0, 1, 'А'); // если замер - "а"ппаратный
else drawChar(37, 0, 1, 'П'); // иначе "п"програмный
float_print(73, 12, 1, vMax * (vRef ? VCC : 1.1) / 255, 2); // рисуем максимальное напряжение сигнала
float_print(78, 54, 1, vMin * (vRef ? VCC : 1.1) / 255, 1); // рисуем минимальное напряжение сигнала
if (vMax==0xFF) for(int y=10; y<68; y++) drawFastHLine( 0, y, 5, 5); // превышение максимума АЦП
// == Отрисовка сетки == //
for (byte i = 11; i < 68; i = i + 14) {
drawFastHLine( 0, i, 2, 1); // черточки слева
}
for (byte i = 67; i > 10; i = i - 4) {
drawPixel(24, i, 1);
drawPixel(48, i, 1);
drawPixel(72, i, 1);
}
for (byte i = 8; i < 96; i = i + 4) {
drawPixel(i, 39, 1);
}
///////////////авто razv//////////////
if (avtorazv)
#define PER 1.3
if (count > 3823.3*PER) razv = 6; else
if (count > 1934.5*PER) razv = 5; else
if (count > 0969.3*PER) razv = 4; else
if (count > 0486.8*PER) razv = 3; else
if (count > 0245.8*PER) razv = 2; else
if (count > 0120.1*PER) razv = 1; else razv = 0;
//bulat если зашкаливает включаем предел 5 в
if (vMax==255){
if (vRef==0)
{
vRef=1;
ADMUX = 0b01100011;// выбор внутреннего опорного 5.0 В
goto label_ReadAdc;
}
}
//bulat если 5 в и уровень менее 1,1 в то вкл предел 1,1 в
if (vMax<=55){
if (vRef==1)
{
vRef=0;
ADMUX = 0b11100011;// выбор внутреннего опорного 1,1В
goto label_ReadAdc;
}
}
//bulat здесь автопредел 1,1/0,22 в,программный
kdel=5;
if (vMax<=55){
if (vRef==0)
{
kdel=1;
}
}
// == Отрисовка графика == //
//for(int y = 0; y < 92; y++) drawLine(y + 4, 67 - adcBuf[y + grOffset]/kdel / 0.9, y + 4, 67 - adcBuf[y + grOffset + 1]/kdel / 0.9, 1);
//progrik: заменил вызов функции рисования _наклонных_линий_ на рисующую простые вертикальные прямые..
for (uint8_t x = 0; x < 92; x++) drawVLineUltraFast(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
Update();
}
smokokзалей плиз проверить. вот теперь вывод ускорен) могу еще, но это уже уровень "ниндзя", новичкам нельзя) глянь теперь на скорость (на паузе особенно). и если вдохновишься результатом - сделай плз видос.)) так же потом можешь в первой строке указать #define BUFSIZE 200 (изменить 800 на 200-300, живьем смотреть намного быстрее станет) а если залагает или не заработает - скажи что и как, гляну. все таки без дисплея легко не заметить баг какой...
smokokзалей плиз проверить. вот теперь вывод ускорен) могу еще, но это уже уровень "ниндзя", новичкам нельзя) глянь теперь на скорость (на паузе особенно). и если вдохновишься результатом - сделай плз видос.)) так же потом можешь в первой строке указать #define BUFSIZE 200 (изменить 800 на 200-300, живьем смотреть намного быстрее станет) а если залагает или не заработает - скажи что и как, гляну. все таки без дисплея легко не заметить баг какой...
Привет! Извини за задержку с ответом. Попробовал, но не запускается. Просто моргает экранчик и нет никакой индикации. Что там подправить я хз.
Попробовал, но не запускается. Просто моргает экранчик и нет никакой индикации. Что там подправить я хз.
привет! а хоть что как моргает? признаки жизни значит есть... сейчас появилось время, погляжу код, что может быть. как чего соображу - сразу дам знать. нужно уже добить раз и навсегда) хоть бери и себе покупай такой дисплей))
Точнее подсветка моргает и тускло светит, а на дисплее ничего нет. Как будто пины не правильно обрабатываются. Пока из китая такой дисплей придёт, то дистационо уже разгонишь))). А ещё же есть 5110)))
..подсветка моргает и тускло светит, а на дисплее ничего нет. Как будто пины не правильно обрабатываются.
о, ты тут. давай через мыло допилим, чтоб форум освободить от ненужных постов) пиши мне на мыло moricz (сбк) ukr после точки net, я буду тебе накидывать варианты кода, пока не найдем затык. а потом уже сюда код шпульнем, чтоб все могли порезвиться)) там по идее не долго искать...
кажется нашел. я сам себя запутал)) вместо опускания ног я их поднимал и наоборот. короче, реверс. исправил пробуй:
#define BUFSIZE 800
#define history 50
volatile int cur_index = 0; //переменная для отсчета замеров
volatile int StartIndex = 0; // номер замера с которого нужно выводить результат (считается так: (замер сработки триггера-предистория))
volatile byte prev_data; // предыдущее состояние шины
volatile byte pattern_mask; // маска для события PATTERN
volatile byte pattern_value; // ЗНАЧЕНИЕ состояния для события PATTERN
volatile boolean trigger_event = false; //признак сработки триггера
volatile int time_disc = 0; // время выборки 1-го значения
unsigned long prevMillis, curMillis;
enum triggerEvents {BURST, MASTER_RISE, MASTER_FALL, PATTERN}; //именнованный список триггеров-событий
bool flag = 0;
// Пины экранчика
#define RES 3
#define CS 4
#define Data 6
#define Clock 7
#define swap(a, b) { byte t = a; a = b; b = t; } //progrik: было int t... работа идет только с byte. так быстрее.
//progrik: порт(ы) для clock, data, reset, chipSelect (CS) согласно распиновке Arduino Nano пины 3,4,6,7 все на порту D
#define CLOCK_PORT PORTD
#define DATA_PORT PORTD
#define RESET_PORT PORTD
#define CS_PORT PORTD
//progrik: маски для порта вывода. для Clock указан пин 7
//progrik: в распиновке Arduino NANO это D7 - порт D пин 7, маска - B10000000. для D0 была бы B00000001 (счет с ноля справа налево)
#define CLOCK_MASK B10000000
#define DATA_MASK B01000000
#define RESET_MASK B00001000
#define CS_MASK B00010000
//progrik: определяем макросы для действий с управляющими пинами
#define CLOCK_IDLE CLOCK_PORT &= ~CLOCK_MASK
#define CLOCK_ACTIVE CLOCK_PORT |= CLOCK_MASK
#define DATA_IDLE DATA_PORT &= ~DATA_MASK
#define DATA_ACTIVE DATA_PORT |= DATA_MASK
#define RESET_IDLE RESET_PORT &= ~RESET_MASK
#define RESET_ACTIVE RESET_PORT |= RESET_MASK
#define CS_IDLE CS_PORT &= ~CS_MASK
#define CS_ACTIVE CS_PORT |= CS_MASK
#include <FreqCount.h>
#include <math.h>
#include <PWM.h>
// Настройки пользователя - можно менять
#define OVERCLOCK 16 // частота на которой работает Ардуино
float VCC = 5.0; // напряжение питания
#define KEY_L 11 // кнопка ЛЕВО (можно любой пин)
#define KEY_OK 12 // кнопка ОК (можно любой пин)
#define KEY_R 13 // кнопка ПРАВО (можно любой пин)
#define VBAT A1 // любой свободный аналоговый пин для измерения напряжения АКБ
#define TempC A0 // любой свободный аналоговый пин для измерения температуры
#define KEY_DELAY 200
#define LCDX 96
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "ОСЦИЛЛОГРАФ"; // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его
const char string_1[] PROGMEM = " ";
const char string_2[] PROGMEM = "VБат.= ";
const char string_3[] PROGMEM = "Temп.= ";
const char string_4[] PROGMEM = " Pause ";
// Теперь создаем таблицу с отсылками к этим строкам:
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4};
char buffer[11]; // массив должен быть достаточно велик, чтобы вместить даже самую большую строку
byte mode = 0; // пункт главного меню
byte menu = 0; // пункт меню
byte adcBuf[BUFSIZE];
byte vSync = 0; // уровень синхронизации
bool vRef = 1; // флаг опорного напряжения
bool pause = 0; // флаг режима паузы
bool avtorazv=1; // Автоматический выбор развертки
byte TextColor = 1;
byte razv = 0;
byte trig = 0;
int kdel=5; //bulat автопредел 1,1/0,22 вольта
int osc=50; // авто вкл. режима осциллографа (секунды)
int grOffset = 0; // смещение графика в рабочем режиме
byte vMax, vMin; // максимальное и минимальное напряжение сигнала
int temp = 0; // временная переменная***
unsigned long count = 1;
byte LCD_RAM[96 * 9]; // 96 * 9
static const char font[] PROGMEM = {
//HEX B DEC переводим
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x20 space
0x00, 0x00, 0x5f, 0x00, 0x00 , // 0x21 !
0x00, 0x07, 0x00, 0x07, 0x00 , // 0x22 "
0x14, 0x7f, 0x14, 0x7f, 0x14 , // 0x23 #
0x24, 0x2a, 0x7f, 0x2a, 0x12 , // 0x24 $
0x23, 0x13, 0x08, 0x64, 0x62 , // 0x25 %
0x36, 0x49, 0x55, 0x22, 0x50 , // 0x26 &
0x00, 0x05, 0x03, 0x00, 0x00 , // 0x27 '
0x00, 0x1c, 0x22, 0x41, 0x00 , // 0x28 (
0x00, 0x41, 0x22, 0x1c, 0x00 , // 0x29 )
0x14, 0x08, 0x3e, 0x08, 0x14 , // 0x2a *
0x08, 0x08, 0x3e, 0x08, 0x08 , // 0x2b +
0x00, 0x50, 0x30, 0x00, 0x00 , // 0x2c ,
0x08, 0x08, 0x08, 0x08, 0x08 , // 0x2d -
0x00, 0x60, 0x60, 0x00, 0x00 , // 0x2e .
0x20, 0x10, 0x08, 0x04, 0x02 , // 0x2f /
0x3e, 0x51, 0x49, 0x45, 0x3e , // 0x30 0
0x00, 0x42, 0x7f, 0x40, 0x00 , // 0x31 1
0x42, 0x61, 0x51, 0x49, 0x46 , // 0x32 2
0x21, 0x41, 0x45, 0x4b, 0x31 , // 0x33 3
0x18, 0x14, 0x12, 0x7f, 0x10 , // 0x34 4
0x27, 0x45, 0x45, 0x45, 0x39 , // 0x35 5
0x3c, 0x4a, 0x49, 0x49, 0x30 , // 0x36 6
0x01, 0x71, 0x09, 0x05, 0x03 , // 0x37 7
0x36, 0x49, 0x49, 0x49, 0x36 , // 0x38 8
0x06, 0x49, 0x49, 0x29, 0x1e , // 0x39 9
0x00, 0x36, 0x36, 0x00, 0x00 , // 0x3a :
0x00, 0x56, 0x36, 0x00, 0x00 , // 0x3b ;
0x08, 0x14, 0x22, 0x41, 0x00 , // 0x3c <
0x14, 0x14, 0x14, 0x14, 0x14 , // 0x3d =
0x00, 0x41, 0x22, 0x14, 0x08 , // 0x3e >
0x02, 0x01, 0x51, 0x09, 0x06 , // 0x3f ?
0x32, 0x49, 0x79, 0x41, 0x3e , // 0x40 @
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x41 A
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x42 B
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x43 C
0x7f, 0x41, 0x41, 0x22, 0x1c , // 0x44 D
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x45 E
0x7f, 0x09, 0x09, 0x09, 0x01 , // 0x46 F
0x3e, 0x41, 0x49, 0x49, 0x7a , // 0x47 G
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x48 H
0x00, 0x41, 0x7f, 0x41, 0x00 , // 0x49 I
0x20, 0x40, 0x41, 0x3f, 0x01 , // 0x4a J
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x4b K
0x7f, 0x40, 0x40, 0x40, 0x40 , // 0x4c L
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x4d M
0x7f, 0x04, 0x08, 0x10, 0x7f , // 0x4e N
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x4f O
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x50 P
0x3e, 0x41, 0x51, 0x21, 0x5e , // 0x51 Q
0x7f, 0x09, 0x19, 0x29, 0x46 , // 0x52 R
0x46, 0x49, 0x49, 0x49, 0x31 , // 0x53 S
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x54 T
0x3f, 0x40, 0x40, 0x40, 0x3f , // 0x55 U
0x1f, 0x20, 0x40, 0x20, 0x1f , // 0x56 V
0x3f, 0x40, 0x38, 0x40, 0x3f , // 0x57 W
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x58 X
0x07, 0x08, 0x70, 0x08, 0x07 , // 0x59 Y
0x61, 0x51, 0x49, 0x45, 0x43 , // 0x5a Z
0x00, 0x7f, 0x41, 0x41, 0x00 , // 0x5b [
0x02, 0x04, 0x08, 0x10, 0x20 , // 0x5c backslash
0x00, 0x41, 0x41, 0x7f, 0x00 , // 0x5d ]
0x04, 0x02, 0x01, 0x02, 0x04 , // 0x5e ^
0x40, 0x40, 0x40, 0x40, 0x40 , // 0x5f _
0x00, 0x01, 0x02, 0x04, 0x00 , // 0x60 `
0x20, 0x54, 0x54, 0x54, 0x78 , // 0x61 a
0x7f, 0x48, 0x44, 0x44, 0x38 , // 0x62 b
0x38, 0x44, 0x44, 0x44, 0x20 , // 0x63 c
0x38, 0x44, 0x44, 0x48, 0x7f , // 0x64 d
0x38, 0x54, 0x54, 0x54, 0x18 , // 0x65 e
0x08, 0x7e, 0x09, 0x01, 0x02 , // 0x66 f
0x0c, 0x52, 0x52, 0x52, 0x3e , // 0x67 g
0x7f, 0x08, 0x04, 0x04, 0x78 , // 0x68 h
0x00, 0x44, 0x7d, 0x40, 0x00 , // 0x69 i
0x20, 0x40, 0x44, 0x3d, 0x00 , // 0x6a j
0x7f, 0x10, 0x28, 0x44, 0x00 , // 0x6b k
0x00, 0x41, 0x7f, 0x40, 0x00 , // 0x6c l
0x7c, 0x04, 0x18, 0x04, 0x78 , // 0x6d m
0x7c, 0x08, 0x04, 0x04, 0x78 , // 0x6e n
0x38, 0x44, 0x44, 0x44, 0x38 , // 0x6f o
0x7c, 0x14, 0x14, 0x14, 0x08 , // 0x70 p
0x08, 0x14, 0x14, 0x18, 0x7c , // 0x71 q
0x7c, 0x08, 0x04, 0x04, 0x08 , // 0x72 r
0x48, 0x54, 0x54, 0x54, 0x20 , // 0x73 s
0x04, 0x3f, 0x44, 0x40, 0x20 , // 0x74 t
0x3c, 0x40, 0x40, 0x20, 0x7c , // 0x75 u
0x1c, 0x20, 0x40, 0x20, 0x1c , // 0x76 v
0x3c, 0x40, 0x30, 0x40, 0x3c , // 0x77 w
0x44, 0x28, 0x10, 0x28, 0x44 , // 0x78 x
0x0c, 0x50, 0x50, 0x50, 0x3c , // 0x79 y
0x44, 0x64, 0x54, 0x4c, 0x44 , // 0x7a z
0x00, 0x08, 0x36, 0x41, 0x00 , // 0x7b {
0x00, 0x00, 0x7f, 0x00, 0x00 , // 0x7c |
0x00, 0x41, 0x36, 0x08, 0x00 , // 0x7d }
0x10, 0x08, 0x08, 0x10, 0x08 , // 0x7e ~
0x00, 0x00, 0x00, 0x00, 0x00 , // 0x7f
0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x80 A // Русские символы
0x7f, 0x49, 0x49, 0x49, 0x33 , // 0x81 Б
0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x82 В
0x7f, 0x01, 0x01, 0x01, 0x03 , // 0x83 Г
0xe0, 0x51, 0x4f, 0x41, 0xff , // 0x84 Д
0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x85 E
0x77, 0x08, 0x7f, 0x08, 0x77 , // 0x86 Ж
0x41, 0x49, 0x49, 0x49, 0x36 , // 0x87 З
0x7f, 0x10, 0x08, 0x04, 0x7f , // 0x88 И
0x7c, 0x21, 0x12, 0x09, 0x7c , // 0x89 Й
0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x8A K
0x20, 0x41, 0x3f, 0x01, 0x7f , // 0x8B Л
0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x8C M
0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x8D H
0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x8E O
0x7f, 0x01, 0x01, 0x01, 0x7f , // 0x8F П
0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x90 P
0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x91 C
0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x92 T
0x47, 0x28, 0x10, 0x08, 0x07 , // 0x93 У
0x1c, 0x22, 0x7f, 0x22, 0x1c , // 0x94 Ф
0x63, 0x14, 0x08, 0x14, 0x63 , // 0x95 X
0x7f, 0x40, 0x40, 0x40, 0xff , // 0x96 Ц
0x07, 0x08, 0x08, 0x08, 0x7f , // 0x97 Ч
0x7f, 0x40, 0x7f, 0x40, 0x7f , // 0x98 Ш
0x7f, 0x40, 0x7f, 0x40, 0xff , // 0x99 Щ
0x01, 0x7f, 0x48, 0x48, 0x30 , // 0x9A Ъ
0x7f, 0x48, 0x30, 0x00, 0x7f , // 0x9B Ы
0x00, 0x7f, 0x48, 0x48, 0x30 , // 0x9C Э
0x22, 0x41, 0x49, 0x49, 0x3e , // 0x9D Ь
0x7f, 0x08, 0x3e, 0x41, 0x3e , // 0x9E Ю
0x46, 0x29, 0x19, 0x09, 0x7f , // 0x9F Я
0x20, 0x54, 0x54, 0x54, 0x78 , // 0xA0 a
0x3c, 0x4a, 0x4a, 0x49, 0x31 , // 0xA1 б
0x7c, 0x54, 0x54, 0x54, 0x28 , // 0xA2 в
0x7c, 0x04, 0x04, 0x04, 0x0c , // 0xA3 г
0xe0, 0x54, 0x4c, 0x44, 0xfc , // 0xA4 д
0x38, 0x54, 0x54, 0x54, 0x18 , // 0xA5 e
0x6c, 0x10, 0x7c, 0x10, 0x6c , // 0xA6 ж
0x44, 0x44, 0x54, 0x54, 0x28 , // 0xA7 з
0x7c, 0x20, 0x10, 0x08, 0x7c , // 0xA8 и
0x7c, 0x41, 0x22, 0x11, 0x7c , // 0xA9 й
0x7c, 0x10, 0x10, 0x28, 0x44 , // 0xAA к
0x20, 0x44, 0x3c, 0x04, 0x7c , // 0xAB л
0x7c, 0x08, 0x10, 0x08, 0x7c , // 0xAC м
0x7c, 0x10, 0x10, 0x10, 0x7c , // 0xAD н
0x38, 0x44, 0x44, 0x44, 0x38 , // 0xAE o
0x7c, 0x04, 0x04, 0x04, 0x7c , // 0xAF п
0x7C, 0x14, 0x14, 0x14, 0x08 , // 0xB0 p
0x38, 0x44, 0x44, 0x44, 0x20 , // 0xB1 c
0x04, 0x04, 0x7c, 0x04, 0x04 , // 0xB2 т
0x0C, 0x50, 0x50, 0x50, 0x3C , // 0xB3 у
0x30, 0x48, 0xfc, 0x48, 0x30 , // 0xB4 ф
0x44, 0x28, 0x10, 0x28, 0x44 , // 0xB5 x
0x7c, 0x40, 0x40, 0x40, 0xfc , // 0xB6 ц
0x0c, 0x10, 0x10, 0x10, 0x7c , // 0xB7 ч
0x7c, 0x40, 0x7c, 0x40, 0x7c , // 0xB8 ш
0x7c, 0x40, 0x7c, 0x40, 0xfc , // 0xB9 щ
0x04, 0x7c, 0x50, 0x50, 0x20 , // 0xBA ъ
0x7c, 0x50, 0x50, 0x20, 0x7c , // 0xBB ы
0x7c, 0x50, 0x50, 0x20, 0x00 , // 0xBC ь
0x28, 0x44, 0x54, 0x54, 0x38 , // 0xBD э
0x7c, 0x10, 0x38, 0x44, 0x38 , // 0xBE ю
0x08, 0x54, 0x34, 0x14, 0x7c , // 0xBF я
};
//********************************************************
// ==== Считывание напряжения питания ардуинки (Vcc) ====
#define Vref11 1.095 // для точной подстройки результата измерений
float ReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // устанавливаем вход АЦП на VCC !!!
delay(1); // задержка для устаканивания АЦП. Можно её избежать, если ADMUX как в строке выше (не менялся)
ADCSRA |= _BV(ADSC); // запуск АЦП преобразования
while (bit_is_set(ADCSRA, ADSC)); // ждем, пока АЦП отработает (выставит бит)
return (Vref11 * 1023.0) / (ADCL | (ADCH << 8)); // результат преобразования в вольтах
}
/////// ==== Температура ==== ////////
double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000)); // 10000=10кОм Для подстройки правим 10000.
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15; // Kelvin to Celcius
return Temp;
}
void setup() {
pinMode(KEY_OK, INPUT); pinMode(KEY_L, INPUT); pinMode(KEY_R, INPUT); // настраиваем кнопки на вход
digitalWrite(KEY_OK, HIGH); digitalWrite(KEY_L, HIGH); digitalWrite(KEY_R, HIGH); // подтяжка к плюсу питания
VCC = ReadVcc();
Inicialize(); //Инициализация дисплея
Clear_LCD();
for (byte i = 0; i < 3; i++)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте
print(10, i * 10, 1, (buffer));
//delay( 500 );
}
Update();
// delay(KEY_DELAY);
while (digitalRead(KEY_OK)) { // цикл, пока не нажали кнопку ОК
Update();
// Если не нажата 10 сек кнопка ок вход в режим осцилоографа автоматом
osc--;
if (osc==0) break;
////////// Выводим показание /////////
float_print(60, 20, 1, analogRead(VBAT)*VCC/1024,1); //Вольтаж батареи
float_print(55, 40, 1, analogRead(TempC), 1); // выводим на экран показание Температуры
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[3]))); // пишем слово "Температура"
print(10, 40, 1, (buffer));
delay( 300 );
} // цикл нажатия ОК
// нажали кнопку ОК из меню, инициализируем и выходим из меню
count = 0; //countX = 0; // восстанавливаем на всякий случай переменные
if (mode == 0) FreqCount.begin(1000);
if (mode == 1) {
InitTimersSafe();
}
if (mode == 2) {
InitTimersSafe();
}
if (mode == 4 || mode == 5) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки
for (char a=37; a>0; a-=2);
}
// беcконечный цикл - по сути прыгаем в подпрограммы
void loop() {
switch (mode) {
// Прыгаем в выбранный режим из главного меню
case 0 : Oscil(); break; // "выпадаем" в осцилл
}
}
// === Читаем с АЦП данные и помещаем их в буфер === //
void ReadAdc() {
if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7)
ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4)
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
adcBuf[i] = ADCH; // записываем данные в массив
}
delay(0.3 * BUFSIZE); // компенсация задержки по сравнению с разверткой 0...
} else { // развертка с задержками (delay)
ADCSRA = 0b11100111; // делитель на /128
for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения
while (!(ADCSRA & 0x10)); // ждем готовность АЦП
ADCSRA |= 0x10; // запускаем следующее преобразование
delayMicroseconds(500); // делаем задержку
adcBuf[i] = ADCH; // записываем данные в массив
}
}
}
// === Чтение цифровых данных со всего порта C (A0...A5) === //
/*void ReadDig() {
if (razv == 9) {
for (int i = 0; i < BUFSIZE; i++) adcBuf[i] = PINC; // быстро читаем данные
} else {
for (int i = 0; i < BUFSIZE; i++) {
adcBuf[i] = PINC; // читаем данные
delayMicroseconds((9 - razv) * 100);
}
}
}*/
// ==== функция вывода float ====
void float_print(byte x, byte y, boolean color, float num, byte zn) { // последняя переменная- кол знаков после запятой
char c[20];
long d = num;
byte m = 1;
while (d > 9) {
d = d / 10;
m++;
}
print(x, y, color, dtostrf(num, m, zn, c));
}
/*int GetCountsOfDigits(int n) //найти количество цифр в числе <a href="<a href="<a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a></a></a>
{
return n < 10 ? 1 :
n < 100 ? 2 :
n < 1000 ? 3 :
n < 10000 ? 4 :
n < 100000 ? 5 :
n < 1000000 ? 6 :
n < 10000000 ? 7 :
n < 100000000 ? 8 :
n < 1000000000 ? 9 : 10;
}*/
// ==== найти количество цифр в числе <a href="<a href="<a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a>" rel="nofollow"><a href="<a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a>" rel="nofollow"><a href="<a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a>" rel="nofollow"><a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a></a></a></a></a>
/*static int stringSize(long x) {
long p = 10;
for (int i = 1; i < 19; i++) {
if (x < p)
return i;
p = 10 * p;
}
return 19;
}*/
void vivod(byte x, byte y, byte n, byte k) { // //Печать цифры размером 24х48 пикселя (x, y, цифра, размер (1-24х48, 2-12х24))
if ((n != 1) && (n != 4)) {
fillRect(x + 3 / k, y, 15 / k, 5 / k, 1 ); // сегмент A
}
if ((n != 5) && (n != 6)) {
fillRect(x + 16 / k, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент B
}
if (n != 2) {
fillRect(x + 16 / k, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент C
}
if ((n != 1) && (n != 4) && (n != 7)) {
fillRect(x + 3 / k, y + 42 / k, 15 / k, 5 / k, 1 ); // сегмент D
}
if ((n == 0) || (n == 2) || (n == 6) || (n == 8)) {
fillRect(x, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент E
}
if ((n != 1) && (n != 2) && (n != 3) && (n != 7)) {
fillRect(x, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент F
}
if ((n != 0) && (n != 1) && (n != 7)) {
fillRect(x + 3 / k, y + 21 / k, 15 / k, 5 / k, 1 ); // сегмент G
}
}
//====================================================указатель меню
/*void ukazatel() {
fillRect(1, 1, 8, 60, 0);
for (byte i = 0; i < 4; i++) { // указатель меню
drawLine(1 + i, mode * 10 + i, 1 + i, mode * 10 + 6 - i, 1);
}
Update();
delay(KEY_DELAY);
}
*/
//===================================================Инициализация дисплея
void Inicialize() {
pinMode(RES, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(Data, OUTPUT);
pinMode(Clock, OUTPUT);
// Инициализация дисплея
//dWrite(RES, 1);
RESET_ACTIVE;
//dWrite(Clock, 0);
CLOCK_IDLE;
//dWrite(Data, 0);
DATA_IDLE;
//dWrite(CS, 0);
CS_IDLE;
delay(20);
//dWrite(CS, 1);
CS_ACTIVE;
SendByte(0, 0x2F); // Power control set(charge pump on/off)
SendByte(0, 0xA4);
SendByte(0, 0xAF); // экран вкл/выкл
//Clear_LCD();
//Update();
CS_IDLE; //progrik: перенес сюда из функции SendByte
}
/*
//=======================================================Управление пинами
//progrik: добалено определение inline. функция встраивается в код и не расходуется воемя на ее вызов.
//progrik: UPD: функция не испольуется, удалить.
inline __attribute__((always_inline)) void dWrite(byte pin, byte val) {
byte bit = digitalPinToBitMask(pin);
volatile byte *out;
out = portOutputRegister(digitalPinToPort(pin));
(val) ? *out |= bit : *out &= ~bit;
}
*/
//=========================================================Отправка 9 байт
//progrik: добалено определение inline. функция встраивается в код и не расходуется время на ее вызов.
//progrik: вместо многократных вызовов функций дергаем ногами при помощи написанных вверху кода макросов
inline __attribute__((always_inline)) void SendByte(byte mode, byte c) {
//dWrite(CS, 0); //progrik: чип селект нужно включить один раз в конце инициализации дисплея, и больше не трогать. перенес в инициализацию
//(mode) ? dWrite(Data, 1) : dWrite(Data, 0);
(mode) ? DATA_ACTIVE : DATA_IDLE;
//dWrite(Clock, 1);
CLOCK_ACTIVE;
for (byte i = 0; i < 8; i++)
{
//dWrite(Clock, 0);
CLOCK_IDLE;
//(c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0);
(c & 0x80) ? DATA_ACTIVE : DATA_IDLE;
//dWrite(Clock, 1);
CLOCK_ACTIVE;
c <<= 1;
}
//dWrite(Clock, 0);
CLOCK_IDLE;
}
//======================================================Очистка дисплея
void Clear_LCD() {
memset(LCD_RAM, 0, 864); //progrik: велосипед не нужен. memset даже чутка быстрее. это из Си.
/*
for (int index = 0; index < 864 ; index++) {
LCD_RAM[index] = (0x00);
}*/
}
//=====================================================Обновить дисплей
void Update() {
for (byte p = 0; p < 9; p++) {
SendByte(0, 0xB0 | p);
SendByte(0, 0x00);
SendByte(0, 0x10);
for (byte col = 0; col < 96; col++) {
SendByte(1, LCD_RAM[(96 * p) + col]);
}
}
}
//===================================================Нарисовать пиксель
//progrik: добалено определение inline. функция встраивается в код и не расходуется время на ее вызов.
//убрана ненужная проверка byte на "меньше ноля" и на вылет за пределы дисплея. не нужно этого допускать в коде.
inline __attribute__((always_inline)) void drawPixel(byte x, byte y, bool color) {
if(color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8);
else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8);
}
//=====================================================Нарисовать букву
void drawChar(byte x, byte y, boolean color, unsigned char c) {
if ((x >= 96) || (y >= 68) || ((x + 4) < 0) || ((y + 7) < 0)) return;
if (c < 128) c = c - 32;
if (c >= 144 && c <= 175) c = c - 48;
if (c >= 128 && c <= 143) c = c + 16;
if (c >= 176 && c <= 191) c = c - 48;
if (c > 191) return;
for (byte i = 0; i < 6; i++ ) {
byte line;
(i == 5) ? line = 0x0 : line = pgm_read_byte(font + (c * 5) + i); // line = EEPROM.read((c * 5) + i);
for (byte j = 0; j < 8; j++) {
// (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color);
if(line & 0x1)
{
drawPixel(x + i, y + j, color);
}
else
{
drawPixel(x + i, y + j, !color);
}
line >>= 1;
}
}
}
//========================================================Вывод строки
void print(byte x, byte y, boolean color, char *str) {
unsigned char type = *str;
if (type >= 128) x = x - 3;
while (*str) {
drawChar(x, y, color, *str++);
unsigned char type = *str;
(type >= 128) ? x = x + 3 : x = x + 6;
}
}
//========================================================Вывод числовых значений
void print(byte x, byte y, boolean color, long num) {
char c[20];
print(x, y, color, ltoa(num, c, 10));
}
//====================================================Рисование линии
void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) {
int steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int err = dx / 2;
int ystep;
(y0 < y1) ? ystep = 1 : ystep = -1;
for (; x0 <= x1; x0++) {
// (steep) ? drawPixel(y0, x0, color) : drawPixel(x0, y0, color);
if(steep)
{
drawPixel(y0, x0, color);
}
else
{
drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
//progrik: добавил функцию для быстрой отрисовки вертикальных линий луча
inline __attribute__((always_inline)) void drawVLineUltraFast(byte x, byte y0, byte y1, boolean color) {
if(y0 > y1)
swap(y0, y1);
do
{
drawPixel(x, y0, color);
}
while(++y0 <= y1);
}
//========================================Рисование вертикальной линии
void drawFastVLine(byte x, byte y, byte h, boolean color) {
byte y1 = y + h - 1;
do
{
drawPixel(x, y, color);
}
while(++y <= y1);
}
//======================================Рисование горизонтальной линии
//progrik: переписал...
void drawFastHLine(byte x, byte y, byte w, boolean color) {
//drawLine(x, y, x + w - 1, y, color); //жутко медленно
byte x1 = x + w - 1;
do
{
drawPixel(x, y, color);
}
while(++x <= x1);
}
//=====================================Рисование залитый прямоугольник
void fillRect(byte x, byte y, byte w, byte h, bool color) {
for(byte i = x; i < x + w; i++) {
//drawFastVLine(i, y, h, color); //progrik: это было медленно
drawVLineUltraFast(x, y, y + h - 1, color);
}
}
//=====================================Рисование битового нолика
void printnull(byte a, byte i) {
drawPixel(29 + a - i * 4, 64, 1);
drawFastVLine(28 + a - i * 4, 65, 2, 1); // и вывести биты на дисплей
drawFastVLine(30 + a - i * 4, 65, 2, 1);
drawPixel(29 + a - i * 4, 67, 1);
}
// === Осциллоскоп === //
void Oscil() {
// установка опорного напряжения АЦП и настройка входа АЦП
ADMUX = vRef ? 0b01100011 : 0b11100011;
label_ReadAdc:
// === Обработка кнопок === //
if (!digitalRead(KEY_L)) switch (menu) { // кнопка лево:)
case 0 : razv--; if (razv == 255) razv = 6; break; // меняем развертку
case 1 : grOffset -= 20; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе
}
if (!digitalRead(KEY_R)) switch (menu) { // кнопка право:)
case 0 : razv++; if (razv == 7) razv = 0; break; // меняем развертку
case 1 : grOffset += 20; if (grOffset > BUFSIZE - LCDX) grOffset = BUFSIZE - LCDX; break; // листаем график в паузе
}
if (!digitalRead(KEY_OK)) switch (++menu) {
case 1: grOffset = 0; pause = 1; break; // вход в паузу - антидребезг типа
case 2: menu = 0; pause = 0; break; // перебор меню
}
////////////////
// === Ведём рассчеты === //
if (!pause) { // если нет паузы
ReadAdc(); // то снимаем осциллограмму
// == Вычисляем максимальное и минимальное значение сигнала == //
vMax = 0; vMin = 0xFF;
for (int y = 1; y < 255; y++) {
if (vMax < adcBuf[y]) vMax = adcBuf[y]; // пока 255, но надо экспериментировать
if (vMin > adcBuf[y]) vMin = adcBuf[y];
}
vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала
// == Определение точки синхронизации == //
bool flagZero = 0; grOffset = 0; // сброс флага и точки синхронизации
// Ищем перепад от меньшего уровня к большему
for (int y = 1; y < BUFSIZE - LCDX; y++) { // смотрим весь массив данных АЦП
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг
if (flagZero && adcBuf[y] > vSync) {
grOffset = y; // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла
break;
}
}
// === Считаем частоту сигнала === //
if (vRef && vMax * VCC / 255 > 2.7) { // если можем замерить аппаратно - меряем
// if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала
} else { // === Меряем частоту сигнала программно === //
flagZero = 0; count = 0; // сброс флага и счетчика
for (int y = grOffset; y < BUFSIZE - LCDX; y++) { // смотрим массив от точки синхронизации до конца
if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг
if (flagZero && adcBuf[y] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период
switch (razv) { // считем частоту периода
case 6: count = 1000000 / ((y - grOffset - 1) * 3.25); break; // делитель 4
case 5: count = 1000000 / ((y - grOffset) * 3.25) / 2; break; // делитель 8
case 4: count = 1000000 / ((y - grOffset) * 3.25) / 4; break; // делитель 16
case 3: count = 1000000 / ((y - grOffset) * 3.25) / 8; break; // делитель 32
case 2: count = 1000000 / ((y - grOffset) * 3.25) / 16; break; // делитель 64
case 1: count = 1000000 / ((y - grOffset) * 3.25) / 32; break; // делитель 128
case 0: count = 1000000 / ((y - grOffset) * 510); break; // делитель 128 тоже
}
break;
}
}
}
count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы
} // закончили вести рассчеты
Clear_LCD(); // чистим экран...
// === Отрисовка меню осцилла ===
// if (vRef) TextColor = 0; else TextColor = 1;
if (vRef) float_print(0, 0, 1, VCC, 1); else {
if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "0.2");
}
if (menu == 0) TextColor = 0; else TextColor = 1; drawChar(21, 0, 1, 'р'); print(27, 0, 1, razv);
if (menu == 1) { // тут задержка для компенсации с остальными задержками
delay(100);
// print(48, 0, 0, " Pause ");
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); // необходимые функции и расшифровки, просто скопируйте
print(48, 0, 0, (buffer));
} else TextColor = 1;
if (!pause) float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты
else { // рисуем прокрутку в режиме паузы
temp = grOffset / 8;
drawFastHLine(temp, 10, 6, 1); drawFastHLine(temp, 9, 6, 1);
} // шкала прокрутки
if (vRef && vMax * VCC / 255 > 2.7) drawChar(37, 0, 1, 'А'); // если замер - "а"ппаратный
else drawChar(37, 0, 1, 'П'); // иначе "п"програмный
float_print(73, 12, 1, vMax * (vRef ? VCC : 1.1) / 255, 2); // рисуем максимальное напряжение сигнала
float_print(78, 54, 1, vMin * (vRef ? VCC : 1.1) / 255, 1); // рисуем минимальное напряжение сигнала
if (vMax==0xFF) for(int y=10; y<68; y++) drawFastHLine( 0, y, 5, 5); // превышение максимума АЦП
// == Отрисовка сетки == //
for (byte i = 11; i < 68; i = i + 14) {
drawFastHLine( 0, i, 2, 1); // черточки слева
}
for (byte i = 67; i > 10; i = i - 4) {
drawPixel(24, i, 1);
drawPixel(48, i, 1);
drawPixel(72, i, 1);
}
for (byte i = 8; i < 96; i = i + 4) {
drawPixel(i, 39, 1);
}
///////////////авто razv//////////////
if (avtorazv)
#define PER 1.3
if (count > 3823.3*PER) razv = 6; else
if (count > 1934.5*PER) razv = 5; else
if (count > 0969.3*PER) razv = 4; else
if (count > 0486.8*PER) razv = 3; else
if (count > 0245.8*PER) razv = 2; else
if (count > 0120.1*PER) razv = 1; else razv = 0;
//bulat если зашкаливает включаем предел 5 в
if (vMax==255){
if (vRef==0)
{
vRef=1;
ADMUX = 0b01100011;// выбор внутреннего опорного 5.0 В
goto label_ReadAdc;
}
}
//bulat если 5 в и уровень менее 1,1 в то вкл предел 1,1 в
if (vMax<=55){
if (vRef==1)
{
vRef=0;
ADMUX = 0b11100011;// выбор внутреннего опорного 1,1В
goto label_ReadAdc;
}
}
//bulat здесь автопредел 1,1/0,22 в,программный
kdel=5;
if (vMax<=55){
if (vRef==0)
{
kdel=1;
}
}
// == Отрисовка графика == //
//for(int y = 0; y < 92; y++) drawLine(y + 4, 67 - adcBuf[y + grOffset]/kdel / 0.9, y + 4, 67 - adcBuf[y + grOffset + 1]/kdel / 0.9, 1);
//progrik: заменил вызов функции рисования _наклонных_линий_ на рисующую простые вертикальные прямые..
for (uint8_t x = 0; x < 92; x++)
drawVLineUltraFast(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1);
Update();
}
seri0shka нет, Украина) хотел дисплей предложить?)) у нас таких есть вроде бакса по полтора, надо глянуть. просто я не уверен, что мне вообще он нужен, а спортивный интерес могу удовлетворить и удаленно без дисплея)) что скоро и сделаю)) и восцарит всеобщая радость)) а позже я покажу демку своего цветного спектроскопа-осциллографа "Spectator" или просто "spectAscope" уровня "ниндзя")) лень допиливать до уровня "БОГ"))) и тогда... потом объясню тебе еще одну мораль..)) кстати, ты говорил о каком-то проекте... если хочешь - тоже маякни на мыло, может чего подскажу, если знаю...
Это не уменьшит ни на байт прошивку, но в коде смотрится гораздо читабельней, особенно для кодеров не уровня "нинзя". Сам нашёл этот секрет совсем недавно, он почему-то практически нигде не упоминается, и очень облегчает жизнь.
В ArduinoIDE можно заменить на ....... Это не уменьшит ни на байт прошивку, но в коде смотрится гораздо читабельней, особенно для кодеров не уровня "нинзя". Сам нашёл этот секрет совсем недавно, он почему-то практически нигде не упоминается, и очень облегчает жизнь.
ниможна)) если нидзя пишет, то он знает, что пишет) ты заглянул в Arduino.h? этот код будет(должен) работать в туеву тучу раз медленнее. я же тут за скорость, а не за простоту написания. я понимаю, в глубокой молодости тоже пытался весь код в одну строку написать. это не правильно) и вот почему (ардуино.х)
сам мне скажи, что тут происходит? в моем случае к порту применяется маска. все. скажу больше. например, при CLOCK_PORT &= ~CLOCK_MASK порт не "читается->применяется маска->пишется в порт", а благодаря тому, что маски для компилятора как константа и оптимизатор понимает, что изменяется только один бит, то он применяет к порту ассемблерную инструкцию sbi/cbi которая выполняется за ДВА такта.
в твоем случае маска может быть неожиданной, и компилятор _возможно_ не сможет это оптимизировать. НО если оптимизатор совсем умный, просто до безобразия, поймет, что в коде больше нет вызова макроса, то может быть и такой код оптимизирует... надо проверить. просто в коде ниндзя я точно знаю, что происходит) а тут (bitvalue) ? ... уже какая-то проверка. зачем? что проверять, если я знаю, что писать... короче, надо проверить скорость... я проверю) если скорость окажется одинаковой - ниндзя пожмет тебе руку и выпишет звездочку))) но продолжу пользоваться портами с масками. меня удручает вызывать что-то, когда ты не знаешь, как это будет работать...
у тебя такой-же дисплей, ты код случайно не затестил? интересно, заработало ли, и что со скоростью, не гнется ли пространство после разгона)))
проверил. таки да, можно. компилятор не запутать такими макросами)) жму руку, вручаю звезду)) ведь можешь, когда захочешь))
проверили с smokok основные функции вывода работают. все полетело. рисование луча и вывод на дисплей 100 кадров - 1,3 сек. надо еще глянуть, как там цифры выводятся и расчеты ведутся. они тоже способны угнетать скорость... но наверное это уже особо и не нужно... найду причину, почему не заводилось, и можно считать этот дисплейчик пройденным этапом в блокноте не держа его в руках)) на удалёнке, на удалёночке))
при "живом" измерении на малых частотах чтобы стало быстрее нужно в буфер читать байт 200+-, а при нажатии на паузу считать всю длину, чтоб было что покрутить на паузе)) а можно на низких синхру ждать прямо в функции чтения ацп и дочитывать ровно 94 или сколько там байт... рекомендую) если конечно оно тебе надо)
Внук помог - написал расчет в массив и загрузка на комп. Осталось быстро-быстро заполнить массив из АЦП в 8266, передать по WiFi на Андроид и получить пультоскоп))
Внук помог - написал расчет в массив и загрузка на комп. Осталось быстро-быстро заполнить массив из АЦП в 8266, передать по WiFi на Андроид и получить пультоскоп))
Внук помог - написал расчет в массив и загрузка на комп. Осталось быстро-быстро заполнить массив из АЦП в 8266, передать по WiFi на Андроид и получить пультоскоп))
в функцию передается тип byte, где он присваивается элементу массива float и выводится как int. это за гранью добра и зла))
проблема не в том, чтобы по вайфай на ведро что-то передать, а в том, _кто_ напишет софт под андроид. а этот код... он ни к чему. он не нужен. это два простейших цикла с кошмарными неправильными и ненужными типами данных, отжирающих память и быстродействие...
у меня есть поломанный черенок от лопаты, осталось накопать золота и получить бабло)))
if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем
сменил на
if (vRef && vMax*VCC/255 > 0.1) { // если можем замерить аппаратно - меряем
В итоге, 5v 1000Гц через делитель 1/10 при опорном 5, частоту не меряет.
2.7 это напряжение при котором переходит измерение частоты на аппаратный режим, ниже 2.7 // === Меряем частоту сигнала программно === //. 2.7 и 2.5 это (возможно) нижний придел, по этому 0.1 вольта при опорном 5, частоту не меряет.
16МГц=3,25микросекунды один замер в частоте периода
27МГц=1,68микросекунды один замер в частоте периода
Прошу извинить с задержкой скетча для НХ1230. Вот ССЫЛКА скачать.
Большое спасибо progrik за проделанную работу и разгон. В скетче только режим осциллографа. Все функции автоматические кроме паузы))). С паузой сильно не заморачивались, но слайдшоу там уже нет. В активном режиме отрисовка и отклик осциллограммы почти мгновенный. С таким же успехом разогнал 5110 от [Electronik83]. Пример можно посмотреть ТУТ.
Так всё ок! И в правду на паузе шустрее стала прокрутка и вообще.
И на посушок такой вопрос, кусокчек кода аналогичен как в 5110 и там в сельсиях, а в 1202 только в фарингейтах! Как так может быть???
smokok, искусственный интеллект в деле: в коде пересчёт Кельвинов в Цельсии, а на выходе Фаренгейты... :)
дальше добавь где-то, например, под функцией DrawLine такую функцию:
а в самом низу 3-я строка снизу, сразу под // == Отрисовка графика == // меняй строку на
и будет еще шустрее... продолжать?)) или хватит? топик загадим) особенно я... надо уходить из топика. отписаться. я вообще сюда случайно иногда захожу. не отписался еще)
Последний изменил так и всё заработало! СПАСИБО!!! ВИДЕО
smokok верни как я говорил, ниже // == Отрисовка графика == // строку c drawLineUltraFast раскомментируй, с drawLine закомментируй. а в самой функции drawLineUltraFast в строке drawPixel(x, y0, color); поменяй в вызове функции x и y0 местами. вот так: drawPixel(y0, x, color); и пробуй.
вижу, на перемотке раза в два быстрее стало, но что-то все равно не то. тут весь код написан так, чтобы убить скорость. был бы у мну такой дисплей - за 5 минут порешал бы его и вывел на орбиту)) но так - тяжеловато.
вообщем, меняй снова и пробуй. там иксы с игреками перепутаны и в них черт ногу сломит... скорее всего с перепутанными х и у прога лезла в область памяти за пределами выделенной, из за этого крешилось...
как я и говорил, тут все написано как для демонстрационной демонстрации демо версии демо прибора для демонстрации демо. все переписывать я не буду. а нужно бы. не мне. тому, кому нужно)) поиграй с чем есть, а мне пока нужно свою работу работать... не запустится функция drawLineUltraFast - верни все взад)) без дисплея совсем грустно такой фигней заниматься.
ЗЫ: а зачем тебе это? у тебя же на фотке дсо138 с паршивкой от GFX вроде. как гласит реклама, "зачем вам этот геморрой?"))
А можно выложить версию чисто под 5110 и oled ,чтоб только один ослик в меню?
а где делось объявление
inline __attribute__((always_inline))
void
drawPixel(...
??? у тебя простоvoid
drawPixel()... ДОПИШИ чтоб стало
inline __attribute__((always_inline))
void
drawPixel(....
и я нашел... перепутал... вместо "<" нужно ">" ... одна ошибка, и точки не выводятся... поменяй функцию drawLineUltraFast
а снизу раскоментируй строку с вызовом drawLineUltraFast, а другую с drawLine закомментируй. скажешь, чё как/
smokok блин. я после while(y0 <= y1) случайно запилил точку с запятой, а вместо "больше" поставил "меньше". в 3-х строках две ошибки. учитесь, пока я жив))
а не компилится - та ладно)... сейчас дам полный код, у меня компилируется
не понимаю, почему у тебя всегда что-то по другому) ты коллапсируешь квантовую волновую функцию где-то не в том месте)) проверяй целиком. жду чё как))
только что изменил, забыл добавить inline __attribute__((always_inline)) перед void drawPixel... проверяй
Учусь - учусь))). Всё норм, запускается! Теперь другое дело, повеселее! Спасибо! Можно считать проект допилен....))). Я скоро на работу до позна ухожу, буду не на связи. Видос делать?
Мой комп при загрузке скетча в синий экран смерти уходит на 10-ке (крыша едет), как я ещё выдерживаю?)))
да, давай видос) пожалуйста) поздравляю с допилом))
Видео HX1230 Testing
нормально) конечно, далеко от идеала, но уже что-то) может в свободное время еще немного подпилю. ускорять еще есть куда и сильно. посмотрим. пока займусь своим цветным чёто-скопом)) надо украсить мир, а то ч/б немного утомили)
del
Подскажите ,почему повторяются строчки?
Не компилиться с ошибкой что нет PWM.h: No such file or directory .Добавил в проект PWM.h -все равно такая же ошибка ..версия IDE 1.8.11
Ничего себе, неделю на форум не заглядывал, а здесь такой прогресс!
progrik, я все функции повытаскивал из чужой библы, ещё и повыбрасывал лишнее, насколько хватает познаний. Просто когда мы пользуемся чужими библиотеками, то многого не замечаем, а здесь всё на виду. Отказ от проверки в drawPixel чреват последствиями, когда контроллер виснет и не реагирует ни на что до перезагрузки, я сталкивался.
Насчёт аппаратного SPI хотелось бы поподробней, как его применить для 9-битной передачи данных на STE2007 (LCD NOKIA 1202/1230)?
И ещё, можно все рекомендации за последнюю неделю форума свести пошагово в одном посте? А то информации много, сложно разобраться.
_кодер_ ОБЯЗАН знать, что делает _каждая_ строка, знать каждую переменную в своем коде. в этом коде шлак засыпан песком и пылью... кода здесь нету.
прикинем, сколько времени шлется 1 байт через функцию SendByte. в ней dWrite вызывается _28_ раз на байт!!! постоянно прижимается чипселект, хотя нужно всего один раз... если она была бы пустая - все равно по 8-12 тактов за вызов, итого 28*8 = минимум 224(!) такта на один байт. и dWrite еще тормознет патамушта и там бред, из 4 строк и кучи ереси нужно всего применить маску к порту. два такта... зачем каждый раз вычислять пин, ты не помнишь куда прицепил проводок? или если не вычислять, то зависнет и перестанет реагировать?... итого получаем 300-500-700-... тактов на байт... это фиаско. это пи*дец _полный_.
аппаратный SPI - есть подозрения, что можно дослать 1 бит руками. но это не точно. я потом узнал, что он 9 бит и авр не держит его.
вот это (mode) ? dWrite(Data, 1) : dWrite(Data, 0); а надо dWrite(Data, mode); в mode уже передается 1 или 0... еще два-три такта наши. там _везде такое_!! долго расписывать... так что даже не юзая аппаратный SPI можно еще раз в 10 ускорить отрисовку. проблема в том, что это уже не поможет. разве что на паузе. остальной код тормозит. сравни видео smokok где без ускорения (на прошлой странице, в посте где он видео с кодом выложил) и с ускорением(чуть выше). при работе почти незаметно. на паузе на перемотке раза в 2,5 быстрее.. в отрисовке код уже менее кривой. но еще кривой. остальной код мне не интересен в силу его слабости. я уже писал, что это все нужно переписать так, что б ты мог себе дать ответ на вопрос про каждую строку, переменную, вызов функции, указатель, время выполнения и возможные способы ускорения. научишься так кодить и задавать себе такие вопросы и знать/находить ответы - код полетит. до этого - только боль)))
вот смотри, в моей функции drawLineUltraFast есть код
вроде все норм. НО. раз кто-то вызвал функцию рисовать линию, то по крайней мере один пиксель будет нарисован. а это значит, что _перед_ первым вызовом drawPixel _не_нужно_ ничего проверять. и получаем ускорение еще на 2 такта. мелочь, а приятно)) получаем:
вот так это работает... почти всегда есть где ускорить)
чуть позже еще гипер-ускорю вывод, что придется замедлять искусственно на перемотке))), и отпишу простыню, что было сделано... ожидайте. ваши страдания важны для нас)))
ЗЫ: сорри за грубость, но так лучше всем. кому надо - быстрее начинают соображать. кому не надо - быстрее поймут, что еще не поздно стать лучшим работником месяца в макдональдс))
Подскажите, пожалуйста, на какой странице последняя версия схемы и программы, 88 страниц тяжко смотреть(
Подскажите, пожалуйста, на какой странице последняя версия схемы и программы, 88 страниц тяжко смотреть(
Смотря под какой дисплей..А так все у Автора на страничке ,остальное уже кто как хотел,тот под себя и перекраивал..
progrik, спасибо за ведро ̶п̶о̶м̶о̶е̶в̶ критики, вот из-за этого начинающие ардуинщики и бросают начатое. Я не брошу, в моём возрасте в макдональдс поздно )
По поводу LCD1202 я код недавно полностью перелопатил (другое применение, там скорость нужна была), в скетче почти годовой давности этого нет. Да в пультоскопе и не особо важна скорость вывода на экран. Сейчас мне интересен другой проект, ваш опыт сильно бы помог, возможно, стОит в личке пообщаться.
progrik, спасибо за ведро ̶п̶о̶м̶о̶е̶в̶ критики, вот из-за этого начинающие ардуинщики и бросают начатое. Я не брошу, в моём возрасте в макдональдс поздно )
По поводу LCD1202 я код недавно полностью перелопатил (другое применение, там скорость нужна была), в скетче почти годовой давности этого нет. Да в пультоскопе и не особо важна скорость вывода на экран. Сейчас мне интересен другой проект, ваш опыт сильно бы помог, возможно, стОит в личке пообщаться.
Не ошибается тот,кто ничего не делает.Сделать выводы и добивать дальше..Не отступать и не сдаваться..
скорость важна и нужна. не неси ересь. с таким кодом даже кнопки хер во время нажимаются, ведь так? а быстрые процессы/всплески, да мало ли чего посмотреть? слайд-шоу в 3 к/с - это херня даже для часов. неужели ты не видел Okmor по моему сделал на внешнем ацп - он тоже разогнал код вывода, так приятно смотреть, хоть и унылое ч/б...
лички тут нет. заводи топик, тебе помогут... может на странице 87-й )) по крайней мере столько страниц было нужно, чтоб я не выдержал и влез разогнать унылое уныние...
короче мне все ясно. одному говорю: -а чего у тебя часы моргают полтора раза в секунду, как попало, вообще не во время и с разными интервалами, в лупе идет постоянный опрос RTC, ведь на модуле есть нога, которая изменяет состояние два раза в секунду(меандр 1 Гц), просто подключи ее на прерывание и рисуй точки ровно прировно раз в пол сек - вкл/выкл и там уже раз в минуту/час/сутки дергай модуль RTC. его ответ был ох*енен: -я это сделал для примера, каждый сам сможет подправить и сделать что захочет.
ВЫ СЕРЬЕЗНО? одному скорость отрисовки в осциллографе не нужна, другой кидает на стол провода, ардуино нано, дисплей, модули, смешал в кучу и говорит - вот что я сделал для вас. это просто демка. вы теперь сможете сделать все сами...
короче, я убеждаюсь, что шапокляк была права. у тебя же говоришь есть гиперскоростной вывод, а тут у человека нет. я все таки допилю исключительно вывод, раз взялся. а дальше - гори оно огнем. раз все уже хорошо.
Да я не обижаюсь, всё-таки когда говорят "ты дурак тут, тут и вот тут" и объясняют причину, то это всё же лучше, чем просто "ты дурак". За подсказки спасибо, приму к сведению, хотя к проекту пультоскопа пока не вернусь, сейчас другие приоритеты. А чтобы показать мой суперскоростной вывод, его нужно привести в соответствие с этим проектом, а на это руки не доходят, потому и не показываю, уж извините. Да и забросают помидорами за "трындец полный".
вот вот вот! Поэтому мечта - через wifi 8266 вывести на Андроид (универсальный экран!) и было бы полегче))
я думал раз в 10 скорость поднимется. но благодаря оптимизатору компилятора этот код хоть как-то работал. браво оптимизаторы компилятора!!)) я убрал ну просто нереальное кол-во вызовов функций - но ускорилось не в 10, а только в 5 раз. ну 5 так 5)) я бы и на аппаратный SPI всю эту хрень повесил, но не имеет смысла, пока есть остальной код...))
чтобы поднять fps "живого" отображения на низких скоростях adc, синхронизацию нужно ловить прямо в функции чтения ацп, и читать буфер до размера дисплея по Х, или чуть больше. а на всю длину буфера читать только по нажатии на паузу. не нужно постоянно считывать килобайт, если ты видишь только 90 байт... разве что немного упадет точность определения частоты...
UPD: вот код. seri0shka вместо простыни все изменения я пометил в комментариях как "progrik". вывод теперь должен херачить как паровоз! если что не понятно - спрашивай
smokok залей плиз проверить. вот теперь вывод ускорен) могу еще, но это уже уровень "ниндзя", новичкам нельзя) глянь теперь на скорость (на паузе особенно). и если вдохновишься результатом - сделай плз видос.)) так же потом можешь в первой строке указать #define BUFSIZE 200 (изменить 800 на 200-300, живьем смотреть намного быстрее станет) а если залагает или не заработает - скажи что и как, гляну. все таки без дисплея легко не заметить баг какой...
Я вот заморочился ради эксперимента, сделал переключатель кварца, можно обновлять,ну или другие проекты создавать на нем.
Точнее подсветка моргает и тускло светит, а на дисплее ничего нет. Как будто пины не правильно обрабатываются. Пока из китая такой дисплей придёт, то дистационо уже разгонишь))). А ещё же есть 5110)))
кажется нашел. я сам себя запутал)) вместо опускания ног я их поднимал и наоборот. короче, реверс. исправил пробуй:
seri0shka нет, Украина) хотел дисплей предложить?)) у нас таких есть вроде бакса по полтора, надо глянуть. просто я не уверен, что мне вообще он нужен, а спортивный интерес могу удовлетворить и удаленно без дисплея)) что скоро и сделаю)) и восцарит всеобщая радость)) а позже я покажу демку своего цветного спектроскопа-осциллографа "Spectator" или просто "spectAscope" уровня "ниндзя")) лень допиливать до уровня "БОГ"))) и тогда... потом объясню тебе еще одну мораль..)) кстати, ты говорил о каком-то проекте... если хочешь - тоже маякни на мыло, может чего подскажу, если знаю...
Вот эту всю простыню
В ArduinoIDE можно заменить на
Это не уменьшит ни на байт прошивку, но в коде смотрится гораздо читабельней, особенно для кодеров не уровня "нинзя". Сам нашёл этот секрет совсем недавно, он почему-то практически нигде не упоминается, и очень облегчает жизнь.
progrik теперь просто белый пустой экран. Я на связи!
проверили с smokok основные функции вывода работают. все полетело. рисование луча и вывод на дисплей 100 кадров - 1,3 сек. надо еще глянуть, как там цифры выводятся и расчеты ведутся. они тоже способны угнетать скорость... но наверное это уже особо и не нужно... найду причину, почему не заводилось, и можно считать этот дисплейчик пройденным этапом в блокноте не держа его в руках)) на удалёнке, на удалёночке))
при "живом" измерении на малых частотах чтобы стало быстрее нужно в буфер читать байт 200+-, а при нажатии на паузу считать всю длину, чтоб было что покрутить на паузе)) а можно на низких синхру ждать прямо в функции чтения ацп и дочитывать ровно 94 или сколько там байт... рекомендую) если конечно оно тебе надо)
Внук помог - написал расчет в массив и загрузка на комп. Осталось быстро-быстро заполнить массив из АЦП в 8266, передать по WiFi на Андроид и получить пультоскоп))
Внук помог - написал расчет в массив и загрузка на комп. Осталось быстро-быстро заполнить массив из АЦП в 8266, передать по WiFi на Андроид и получить пультоскоп))
Достойно новой темы-с удовольствием бы потестил.
проблема не в том, чтобы по вайфай на ведро что-то передать, а в том, _кто_ напишет софт под андроид. а этот код... он ни к чему. он не нужен. это два простейших цикла с кошмарными неправильными и ненужными типами данных, отжирающих память и быстродействие...
у меня есть поломанный черенок от лопаты, осталось накопать золота и получить бабло)))
ставьте перед собой реальные цели))
Доброго времени суток.
Я дико извиняюсь, но можно ли как то это вот все адаптировать под ssd1306?)
weisswp, на предыдущей странице, Enjoy даже фото готового прибора выложил с экраном 1306. Ищите скетчи от Electronik83, все адаптировано уже.
weisswp, на предыдущей странице, Enjoy даже фото готового прибора выложил с экраном 1306. Ищите скетчи от Electronik83, все адаптировано уже.
Спасибо :)
Тогда сменил 2.7 на 0.1 в этой строке
В итоге, 5v 1000Гц через делитель 1/10 при опорном 5, частоту не меряет.
16МГц=3,25микросекунды один замер в частоте периода
27МГц=1,68микросекунды один замер в частоте периода
Сделаль чудо девайс!!! У меня вопрось: Какие значение измеряеть на вольтах,т,е Vrms или Vpp или Vp?
V=Vrms,Vpp,Vp ???
[...было много буков...]
Прошу извинить с задержкой скетча для НХ1230. Вот ССЫЛКА скачать.
Большое спасибо progrik за проделанную работу и разгон. В скетче только режим осциллографа. Все функции автоматические кроме паузы))). С паузой сильно не заморачивались, но слайдшоу там уже нет. В активном режиме отрисовка и отклик осциллограммы почти мгновенный. С таким же успехом разогнал 5110 от [Electronik83]. Пример можно посмотреть ТУТ.
Скетч использует 9486 байт (29%) памяти устройства. Всего доступно 32256 байт.
А можно скетч под 5110 ?