Подключаем внешнюю флеш-память SD-Card к МиниБоту
Здесь я постараюсь оформить свои давние мысли о применении памяти в элементах ИИ.
Если подходить к памяти с точки зрения организации элементов ИИ, то для начала для начала несколько фактов:
1. Флеш-память нынче дешева как никогда и при этом постоянно цена еще падает чутли не ежемесячно. По состоянию на 5 июля 2008г. 2Гб micro-SD в розницу стоила 268р. при этом она умещается на ногте и имеет толщину меньше 1мм.
2. Операция поиска у живых организмов происходит параллельно, а не последовательно как принято у нас в программировании. А именно, из милллиона записей БД мы в программировании чтоб найти что либо должны перебрать почти весь список т.е. нам потребуется почти миллион тактов на поиск, у живых же организмов на это уходит несколько тактов при этом размер базы для них не имеет никакого значения. Мы конечно применяем разного рода ухищрения в виде предварительной сортировки и индексации, но это всё от безисходности. Факт остается фактом, чем больше БД тем больше времени уходит на поиск. При этом как такого тактования применяемого сейчас сплош и рядом в микропроцессорах у живых организмов нет. А оно собственно и не надо. Посмотрите как работает паралельная озушка, у нее никакого тактового нет. Но об этом чуть позже...
3. флеш-память можно расматривать как скучкованную в одном месте гору микросхем отдельных памятей по 512 байт. В случае с вышеупомянутой 2ГБ карточкой это 3.967.488 микросхемок по 512Кб
Итак для примера рассмотрим самый простой пример, необходимо подсчитать общее количество единичек поступивших на вход, у нас есть три пути:
--- С помощью микроконтроллера или микропроцессора написать соответсвующий последовательный код. Вывод чем больше у нас входов тем дольше мы будем подсчитывать.
--- С помощью логики собрать схему приведенную на рисунке 11.12 Тут всё хорошо никакого тактования, подсчет происходит мгновенно. Одно плохо, если необходимо увеличить количество входов, то прийдется перепаивать схему.
--- Собрать схему на флешевой памяти. Входа в нашем случае это адресные линии, выход это шина данных. Ложка дегтя которая сразу бросается в глаза, такой вариант прийдется обучать. Но позвольте господа, именно так у живых существ и просиходит! И помоему мы как раз этого и добивались! :-) И обучать-то прийдется всего только один раз, при современных скоростях это займет доли секунд
И вот тут мы плавно и незаметно подошли к понятию ассоциативной памяти.
Схеме на базе памяти по большому счету всё равно что там у нее на входах, она четко запомнила, когда на входе то-то, то на выходе должно быть то-то. Я считаю что такому принципу работает любой нейрон, хоть сложения хоть вычитания с умножением, хоть распознования образов. Т.е. в процессе обучения устанавливается ассоциация входного сигнала с номером образа.
<source lang="vb">
$prog &HFF , &HE4 , &HD9 , &HFF ' generated. Take care that the chip supports all fuse bytes. $regfile = "m128DEF.dat" $crystal = 8000000 $baud = 4800
'Нога отвечает за Вкл/Откл SD карты в SPI режиме Config Porte.2 = Output : Chip_select Alias Porte.2
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4
Dim Флаг As Bit Dim ФлагПроверкиЗаписи As Bit Dim ФлагДанныеЗаписаныВерно As Bit
Dim ПринятыйБайт As Byte Dim Sd_command(6) As Byte 'Ответ максимум состоит из 10 байт Dim Size_answer As Byte Dim Sd_answer(10) As Byte Dim Sd_data(512) As Byte
Dim Tmp_byt1 As Byte Dim Tmp_byt2 As Byte Dim Tmp_byt3 As Byte
Dim Count_wrd As Word
Dim Tmp_wrd1 As Word Dim Tmp_wrd2 As Word
Dim Sd_address As Long
Print "Старт программы"
Begin: Chip_select = 1 'Отключить SD карту 'Ответ максимум состоит из 1 байт Size_answer = 1 ФлагПроверкиЗаписи = 0 Sd_address = &H0
Spiinit 'Инициализация SPI у меги
Gosub Init_sd 'Инициализация SPI у SD карты
Do Gosub Clear_sd_buffer 'Очистить буфер для чтения/записи SD карты
Sd_data(1) = 10 Sd_data(2) = 20 Sd_data(3) = 30 Sd_data(4) = 40 Sd_data(5) = 50 Sd_data(6) = 60 Sd_data(7) = 70 Sd_data(8) = 80 Sd_data(9) = 90 Sd_data(10) = 100
Gosub Write_sd_data 'Записать данные в SD карту
Gosub Read_sd_data 'Прочитать данные из SD карты
Sd_address = Sd_address + 512
Loop Until Sd_address = 2048
End
'-------------------------------------------------------------------------------
Init_sd: 'Подпограмма инициализирует SPI у SD карты
Print "Инициализация SPI у SD карты"
'Переводим SD карту в SPI режим ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff)
Chip_select = 0 'Включить SD карту
Print "Ресет" 'Послать команду ресет SD карты Sd_command(1) = &H40 Sd_command(2) = &H00 Sd_command(3) = &H00 Sd_command(4) = &H00 Sd_command(5) = &H00 Sd_command(6) = &H95 Gosub Send_sd_command
Print "Инициализация"
Do 'Послать команду инициализации SD карты Sd_command(1) = &H41 Sd_command(2) = &H00 Sd_command(3) = &H00 Sd_command(4) = &H00 Sd_command(5) = &H00 Sd_command(6) = &H55 Gosub Send_sd_command Waitms 100 Loop Until Sd_answer(1) = 0
Chip_select = 1 'Отключить SD карту
Print "Инициализация SPI у SD карты окончена" Return
Send_sd_command: 'Подпограмма посылает команду SD карте
ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(sd_command(1)) ПринятыйБайт = Spimove(sd_command(2)) ПринятыйБайт = Spimove(sd_command(3)) ПринятыйБайт = Spimove(sd_command(4)) ПринятыйБайт = Spimove(sd_command(5)) ПринятыйБайт = Spimove(sd_command(6))
Gosub Receive_sd_command 'Получить ответ от SD карты
ПринятыйБайт = Spimove(ПринятыйБайт) Return
Receive_sd_command: 'Подпограмма получает ответ от SD карты
Do ПринятыйБайт = Spimove(&Hff) Loop Until ПринятыйБайт <> &HFF
Tmp_byt1 = 0
Do Incr Tmp_byt1 Sd_answer(tmp_byt1) = ПринятыйБайт ПринятыйБайт = Spimove(&Hff) Loop Until ПринятыйБайт = &HFF Or Size_answer = Tmp_byt1
Print "Ответ SD карты" For Tmp_byt2 = 1 To Tmp_byt1
Print "Байт №" ; Tmp_byt2 ; " = " ; Sd_answer(tmp_byt2)
Next Return
Clear_sd_buffer: 'Подпограмма очищяет буфер для чтения/записи SD карты
For Count_wrd = 1 To 512
Sd_data(count_wrd) = 0
Next Return
Write_sd_data: 'Подпограмма записывает данные в SD карту по адресу Sd_address размером 512 байт 'данные берёт из Sd_data(512)
Do Tmp_byt3 = 0 Do Флаг = 0 Chip_select = 0 'Включить SD карту
Print "Запись"
Print "Записать блок данных (512 байт) по адресу " ; Hex(sd_address)
Do Incr Tmp_byt3 Print "Попытка записать данные №" ; Tmp_byt3 Sd_command(1) = &H58 'Послать команду записать блок данных по адресу (sd_address) в SD карту
Tmp_wrd1 = Highw(sd_address) Tmp_wrd2 = Sd_address
Sd_command(2) = High(tmp_wrd1) Sd_command(3) = Low(tmp_wrd1) Sd_command(4) = High(tmp_wrd2) Sd_command(5) = Low(tmp_wrd2) Sd_command(6) = &H55 Gosub Send_sd_command Loop Until Sd_answer(1) = 0 Or Tmp_byt3 = 5
If Sd_answer(1) <> 0 Then Флаг = 1 'Команда на запись не прошла Print "Пришёл неверный ответ от команды записи" Else Print "Послать данные" ПринятыйБайт = Spimove(&Hff) 'Послать данные ПринятыйБайт = Spimove(&Hfe) 'Послать стартовые байты 'Послать данные For Count_wrd = 1 To 512 ПринятыйБайт = Spimove(sd_data(count_wrd)) Next 'Послать CRC16 ПринятыйБайт = &H55 ПринятыйБайт = Spimove(ПринятыйБайт) ПринятыйБайт = &H55 ПринятыйБайт = Spimove(ПринятыйБайт)
Gosub Receive_sd_command 'Получить ответ от SD карты
If Sd_answer(1) <> 229 Then Sd_answer(1) = 1 'Данные не записались If Tmp_byt3 = 5 Then Флаг = 1 Print "Пришёл неверный ответ после записи данных" End If Else ПринятыйБайт = Spimove(&Hff)
Chip_select = 1 'Отключить Sd карту
ПринятыйБайт = Spimove(&Hff)
Chip_select = 0 'Включить SD карту
ПринятыйБайт = Spimove(&Hff)
Print "Данные успешно записаны" Sd_answer(1) = 0 End If End If
Chip_select = 1 'Отключить Sd карту Waitms 10 'Время, которое неоюходимо, для записи данных в SD карту
If Флаг = 1 Then Tmp_byt3 = 0 'Произошла ошибка при записи команды или данных Gosub Init_sd 'Инициализация SPI у SD карты End If Loop Until Флаг = 0 And Sd_answer(1) = 0 ФлагПроверкиЗаписи = 1 'Проверить правильно ли записали Gosub Read_sd_data 'Прочитать данные из SD карты
If ФлагДанныеЗаписаныВерно = 1 Then Print "Верификация прошла успешно" Else Print "Верификация не прошла" End If Loop Until ФлагДанныеЗаписаныВерно = 1
Return
Read_sd_data: 'Подпограмма читает данные из SD карты по адресу Sd_address размером 512 байт 'данные записывает в Sd_data(512) ФлагДанныеЗаписаныВерно = 1
Do Флаг = 0 Chip_select = 0 'Включить SD карту
If ФлагПроверкиЗаписи = 1 Then Print "Верификация" Else Print "Чтение" End If
Print "Установить размер блока чтения данных - 512" 'Послать команду установить размер блока 512 в SD карту Sd_command(1) = &H50 Sd_command(2) = &H00 Sd_command(3) = &H00 Sd_command(4) = &H02 Sd_command(5) = &H00 Sd_command(6) = &H55 Gosub Send_sd_command
Print "Прочитать блок данных по адресу " ; Hex(sd_address) 'Послать команду прочитать блок данных по адресу (sd_address) в SD карту
Tmp_byt3 = 0 Do Incr Tmp_byt3 Print "Попытка прочитать данные №" ; Tmp_byt3 Sd_command(1) = &H51
Tmp_wrd1 = Highw(sd_address) Tmp_wrd2 = Sd_address
Sd_command(2) = High(tmp_wrd1) Sd_command(3) = Low(tmp_wrd1) Sd_command(4) = High(tmp_wrd2) Sd_command(5) = Low(tmp_wrd2) Sd_command(6) = &H55 Gosub Send_sd_command Loop Until Sd_answer(1) = 0 Or Tmp_byt3 = 5
If Sd_answer(1) <> 0 Then Флаг = 1 'Команда на чтение не прошла Print "Пришёл неверный ответ от команды чтения" Else 'Получение данных 'Поймать стартовый байт Do ПринятыйБайт = Spimove(&Hff) Loop Until ПринятыйБайт = &HFE For Count_wrd = 1 To 512 'Получить 512 байт данных If ФлагПроверкиЗаписи = 1 Then ПринятыйБайт = Spimove(&Hff) 'Читаем и сравниваем с Sd_data(512) If ПринятыйБайт <> Sd_data(count_wrd) Then ФлагДанныеЗаписаныВерно = 0 End If Else Sd_data(count_wrd) = Spimove(&Hff) 'Читаем и записываем в Sd_data(512) End If Next 'Получить КС ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff)
Print "Данные успешно считаны" End If
Chip_select = 1 'Отключить Sd карту'
If Флаг = 1 Then 'Произошла ошибка при записи команды или данных
Gosub Init_sd 'Инициализация SPI у SD карты End If Loop Until Флаг = 0
ФлагПроверкиЗаписи = 0 Return
</source>