'*******************************************************************************
'* Filename    : Сумеречный переключатель                                      *
'* Revision    : 1.0                                                           *
'* Controller  : ATMEGA8                                                       *
'* Compiler    : BASCOM-AVR 1.11.9.0                                           *
'* Author      : MACTEPOK                                                      *
'*******************************************************************************
$regfile = "m8def.dat"                                      'определяем контроллер
$crystal = 4000000                                          'внутренний генератор
'$sim
$lib "mcsbyte.lbx"                                          'подключаем библиотеку функций

Config Pinc.0 = Input : Portc.0 = 1                         'кнопка УСТ
Config Pinc.1 = Input : Portc.1 = 1                         'кнопка Вверх
Config Pinc.2 = Input : Portc.2 = 1                         'кнопка Вниз
'Config Watchdog = 2048
'Start Watchdog
Config Portd = Output : Config Portb = Output               'порты на выход к которым подключен индикатор
Load1 Alias Portb.3                                         'нагрузка №1
Config Adc = Single , Prescaler = Auto , Reference = Avcc   'настраиваем АЦП

Dim W As Byte : Dim Y As Byte : Dim X As Byte : Dim I As Byte : Dim Z As Byte : Dim Chislo(8) As Integer : Dim Light As Integer : Dim Light_on As Byte : Dim Light_off As Byte : Dim Sostoyanie As Byte : Dim Copy_print As Integer : Dim _print As Integer : Dim Pokazaniya As Integer : Dim View_menu As Byte
Dim On_flag As Bit                                          'флаг режима настройки уставки ON
Dim Off_flag As Bit                                         'флаг режима настройки уставки OFF
Dim Set_flag As Bit                                         'флаг режима меню
Dim Podskaz_flag As Bit                                     'флаг режима отображения подсказки

A Alias Portd.5 : B Alias Portd.7 : C Alias Portd.3 : D Alias Portd.1       'порты, к которым подключены сегменты индикатора
E Alias Portd.0 : F Alias Portd.6 : G Alias Portd.4 : H Alias Portd.2       '
Dig1 Alias Portb.0 : Dig2 Alias Portb.1 : Dig3 Alias Portb.2       '  порты, к которым подключены общие провода каждой цифры
For X = 1 To 3                                              ' присваиваем всем цифрам пустоту, чтоб в момент включения не высвечивались ноли
Chislo(x) = 11
Next

Config Timer0 = Timer , Prescale = 8 : On Timer0 Pulse      ' конфигурируем таймер 0 и назначаем подпрограмму которая выполняется при переполнении таймера
Config Timer1 = Timer , Prescale = 1 : On Timer1 Bootons    ' конфигурируем таймер 1 и назначаем подпрограмму которая выполняется при переполнении таймера
Enable Interrupts : Enable Timer0 : Enable Timer1           ' разрешаем прерывания, таймер 0,   таймер 1
Start Timer0 : Start Timer1
   Readeeprom Light_on , 0                                  ' Считываем из EEPROM уставку ON
   Readeeprom Light_off , 5                                 ' Считываем из EEPROM уставку OFF
   If Light_off = 255 Then Light_off = 50
   If Light_on = 255 Then Light_on = 40
   Start Adc

Do


   If X > 8 Then
      Stop Timer0 : Stop Timer1
      Light = Getadc(5)                                     'опрос фоторезистора
      Light = Light / 10                                    'пересчет
'      Light = Light - 10
      If Light > 100 Then Light = 100
   X = 0                                                    ' чтобы показания не скакали
   End If
   Start Timer0 : Start Timer1

   If Light <= Light_on Then Sostoyanie = 1                 'если освещенность ниже уставки ON, то включаем нагрузку
   If Light >= Light_off Then Sostoyanie = 0                'если освещенность выше уставки OFF, то выключаем нагрузку
   If Sostoyanie = 1 Then : Set Load1 : Else : Reset Load1 : End If
Loop

'*******************************************************************************
' Индикация
'Reset Watchdog
Pulse:
   H = 1
   Stop Timer0                                              'останавливаем таймер 0
   _print = Light                                           'запись показаний  освещенности на индикатор
   If On_flag = 1 Then _print = Light_on                    'если режим настройки уставки ON,то на индикатор уставку ON
   If Off_flag = 1 Then _print = Light_off                  'если режим настройки уставки OFF,то на индикатор уставку OFF

   If Podskaz_flag = 0 Then                                 'если не выводим на индикатор подсказки, то работаем с числами
      Copy_print = _print                                   'скопируем переменную до обработки

         For I = 1 To 3                                     ' цикл в котором разбивается переменная на 3 числа
         Chislo(i) = _print Mod 10                          ' заносим в масив последнюю цифру от числа _print(123 mod 10 = 3)
         _print = _print / 10                               ' отсекаем последнюю цифру от числа Temp_print (123/10=12)
      Next
      If Copy_print < 100 Then Chislo(3) = 11               'если  переменная < 100, то устанавливаем в 3м индикаторе пустоту
      If Copy_print < 10 Then Chislo(2) = 11                ' если  переменная < 10, то устанавливаем в 2м индикаторе пустоту
   End If


   Reset Dig1 : Reset Dig2 : Reset Dig3
   Incr W : If W > 4 Then W = 1                             ' выбираем какую цифру сейчас включать
   Y = 0
   Gosub Look : A = Z                                       ' переходим к подпрограмме Look, которая определяет нужно ли сейчас загорется сегменту А
   Gosub Look : B = Z
   Gosub Look : C = Z
   Gosub Look : D = Z
   Gosub Look : E = Z
   Gosub Look : F = Z
   Gosub Look : G = Z

   Select Case W                                            ' включаем цифру которую выбрали (w). Подаем плюс на общий провод конкретной цифры
      Case 1 :
         Set Dig1
      Case 2 :
         Set Dig2
      Case 3 :
         Set Dig3
   End Select
   Start Timer0
Return
'
Look:                                                       ' подпрограмма которая определяет нужно ли сейчас гореть сегменту, который вызвал эту подпрограмму
   Z = Chislo(w) * 7 : Z = Y + Z                            ' определяем порядковый номер числа из таблици DATA. W - это цифра которую будем выводить 1..2..3, Y это номер сегмента (A=0 B=1 C=2...G=7)
   Z = Lookup(z , Cifri)                                    ' выбираем из таблици включить или выключить нужный сегмент
   Incr Y                                                   'Y это номер сегмента (A=0 B=1 C=2...). Chislo(w) * 7 - переход на начало нужной строки Data.Z = Y + Z - по очереди перебираем сегменты в строке.
Return
'
Cifri:
' таблица сегментом для индикаторов с общим плюсом      |Chislo(i)| Символ |
Data 0 , 0 , 0 , 0 , 0 , 0 , 1                              '0
Data 1 , 0 , 0 , 1 , 1 , 1 , 1                              '1
Data 0 , 0 , 1 , 0 , 0 , 1 , 0                              '2
Data 0 , 0 , 0 , 0 , 1 , 1 , 0                              '3
Data 1 , 0 , 0 , 1 , 1 , 0 , 0                              '4
Data 0 , 1 , 0 , 0 , 1 , 0 , 0                              '5
Data 0 , 1 , 0 , 0 , 0 , 0 , 0                              '6
Data 0 , 0 , 0 , 1 , 1 , 1 , 1                              '7
Data 0 , 0 , 0 , 0 , 0 , 0 , 0                              '8
Data 0 , 0 , 0 , 0 , 1 , 0 , 0                              '9
Data 1 , 1 , 1 , 1 , 1 , 1 , 0                              '10           "-"
Data 1 , 1 , 1 , 1 , 1 , 1 , 1                              '11           ""
Data 1 , 1 , 1 , 0 , 0 , 0 , 1                              '12           "L"
Data 1 , 1 , 0 , 1 , 0 , 1 , 0                              '13           "n"
Data 0 , 1 , 1 , 1 , 0 , 0 , 0                              '14           "F"
Data 0 , 1 , 1 , 0 , 0 , 0 , 0                              '15           "E"
Data 1 , 1 , 1 , 1 , 0 , 1 , 0                              '16           "r"
Data 1 , 1 , 1 , 1 , 0 , 0 , 1                              '17           "I"
Data 0 , 0 , 0 , 1 , 1 , 0 , 0                              '18           "g"

'*******************************************************************************
'
'*******************************************************************************
' Опрос кнопок
Bootons:
   Incr X
   Stop Timer1
   Do
      If Pinc.0 = 0 Then Gosub Set_mode                     ' Нажатие кнопки УСТ
      Bitwait Pinc.0 , Set                                  'Ждем, пока отпустят кнопку УСТ
      If Set_flag = 1 Then                                  'Кнопки Вверх и Вниз активны только после входа в меню
         If Pinc.1 = 0 Then Gosub Up_const
         If Pinc.2 = 0 Then Gosub Down_const
      End If
   Loop Until View_menu = 0                                 'Опрос кнопок в бесконечном цикле, пока не выйдем из меню
   Enable Interrupts : Enable Timer0 : Start Timer0 : Start Timer1
Return
'*******************************************************************************
'
'
Set_mode:
   Enable Interrupts : Enable Timer0 : Start Timer0
   Set Podskaz_flag                                         'Поднимаем флаг вывода подсказок (буквы)
   Incr View_menu                                           'пункты меню

   If Light_on >= Light_off Then Gosub Errors               'Блокировка ввода уставок. Чтобы свет включался только ночью!
   If View_menu >= 3 Then View_menu = 0

      Select Case View_menu
       Case 0 :                                             'показываем 'LIg' (Light)
           Chislo(1) = 6
           Chislo(2) = 17
           Chislo(3) = 12
           Reset Set_flag                                   'режим отображения текущего значения освещенности
           Reset On_flag                                    '
           Reset Off_flag
           Writeeeprom Light_off , 5
           Waitms 500


           Case 1 :                                         ' On
           Chislo(1) = 11
           Chislo(2) = 13
           Chislo(3) = 0
           Set Set_flag
           Set On_flag                                      'режим отображения уставки ON
           Reset Off_flag
           Waitms 500

           Case 2 :                                         ' OFF
           Chislo(1) = 14
           Chislo(2) = 14
           Chislo(3) = 0
           Set Set_flag
           Reset On_flag
           Set Off_flag                                     'режим отображения уставки OFF
           Writeeeprom Light_on , 0
           Waitms 500

           End Select

   Reset Podskaz_flag
Return
'
Errors:
   Chislo(1) = 16
   Chislo(2) = 16                                           'Выводим подсказку Err и мигаем
   Chislo(3) = 15
   Waitms 500
   Chislo(1) = 11
   Chislo(2) = 11
   Chislo(3) = 11
   Waitms 500
   Chislo(1) = 16
   Chislo(2) = 16
   Chislo(3) = 15
   Waitms 500
   Chislo(1) = 11
   Chislo(2) = 11
   Chislo(3) = 11
   Waitms 500

   If On_flag = 1 Then Readeeprom Light_on , 0              'Если были в 1 пункте меню, возвращаем прежнюю уставку ON из EEPROM
   If Off_flag = 1 Then Readeeprom Light_off , 5            'Если были во 2 пункте меню, возвращаем прежнюю уставку OFF из EEPROM
   Decr View_menu
Return
'
Up_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   If On_flag = 1 Then                                      'если в режиме отображения уставки ON
      Do
         Incr Light_on
         Waitms 50
         If Light_on >= 100 Then Light_on = 100
      Loop Until Pinc.1 = 1
   End If
   If Off_flag = 1 Then                                     'если в режиме отображения уставки OFF
      Do
         Incr Light_off
         Waitms 50
         If Light_off >= 100 Then Light_off = 100
      Loop Until Pinc.1 = 1
   End If
Return
'
'
Down_const:
   Enable Interrupts : Enable Timer0 : Start Timer0
   If On_flag = 1 Then                                      'если в режиме отображения уставки ON
      Do
         Decr Light_on
         Waitms 50
         If Light_on <= 1 Then Light_on = 1
      Loop Until Pinc.2 = 1
   End If
   If Off_flag = 1 Then                                     'если в режиме отображения уставки OFF
      Do
         Decr Light_off
         Waitms 50
         If Light_off <= 2 Then Light_off = 2
      Loop Until Pinc.2 = 1
   End If
Return









