LINUX.ORG.RU

Избранные сообщения Bfgeshka

GCLI 2.10.0

Новости — Разработка
Группа Разработка

31 декабря, после почти трёх месяцев разработки, состоялся выпуск 2.10.0 консольной утилиты GCLI, предназначенной для взаимодействия с API нескольких популярных сервисов хостинга Git-проектов, и позволяет создавать, просматривать и взаимодействовать с проблемами, запросами на слияние, метками и комментариями к ним, проверять состояние CI и конвейеров, и многое другое.

И, в отличие от GitHub CLI, GCLI поддерживает не только API GitHub, но и API GitLab, Gitea, Forgejo и Bugzilla.

( читать дальше... )

>>> Подробности на GitHub

 , , , ,

dataman
()

Покажите видео как вы программируете

Форум — Talks

Думаю будет интересно посмотреть среду, инструменты, процесс.

Вот моё

AZJIO
()

С Новым годом!

Новости — Linux.org.ru
Группа Linux.org.ru

Администрация форума поздравляет всех участников форума и анонимусов, причастных к миру Open Source, с наступающим или даже уже у кого-то наступившим Новым 2026 годом!

Традиционно желаем вам долгого аптайма, стабильного линка и успешного завершения всех процессов с нулевым кодом возврата.

Ну и куда ж без конкурсов? Заходите под кат за интересностями!

( читать дальше... )

 

Zhbert
()

Какой последний музыкальный трек вас зацепил?

Форум — Talks

Поделитесь музыкой, треком, тем что вас зацепило переслушивать по несколько раз.

Вот моё: Вивальди - Зима, рок-обработка

AZJIO
()

IWYU 0.21

Новости — Разработка
Группа Разработка

Вышел релиз IWYU (или include-what-you-use), программы позволяющей находить избыточные и предлагать недостающие #include в вашем коде на C/C++.

( читать дальше... )

>>> Подробности

 , iwyu

NickNotNick
()

Файловый менеджер на C++/Qt

Галерея — Скриншоты

Всем общий привет!

Я начинающий разработчик на C++/Qt и хочу показать свой первый более-менее крупный проект – простой файловый менеджер под Linux.

Сейчас он умеет:

  • просматривать файлы и директории;
  • копировать их, вырезать и вставлять;
  • перетаскивать файлы (drag & drop);
  • работать с несколькими выделенными элементами и т. д.

Все операции выполняются через стандартные утилиты GNU/Linux – cp, mv, rm, ведь версия для Windows только в планах.

( читать дальше... )

 , , ,

DadyaIgor
()

Проверка большого числа условий на си

Форум — Development

Сейчас я пишу такой код:

	if( phonebookEntry->index < 0 && phonebookEntry->telNo && !phonebookEntry->name ){
		//только телефон
	}else if( phonebookEntry->index < 0 && phonebookEntry->telNo && phonebookEntry->name ){
		//телефон и имя
	}else if( phonebookEntry->index >= 0 && !phonebookEntry->telNo && !phonebookEntry->name ){
		//только индекс
	}else if( phonebookEntry->index >= 0 && phonebookEntry->telNo && !phonebookEntry->name ){
		//индекс и телефон
	}else if( phonebookEntry->index >= 0 && phonebookEntry->telNo && phonebookEntry->name ){
		//индекс, телефон и имя
	}else{
		//недопустимое сочетание
	}

И я заметил, что в каждом условном операторе сразу проверяется случая и подумал, а что если поступить вот так:

	unsigned int condition = 0;
	
	if( phonebookEntry->index >= 0 ) condition |= 1;
	if( phonebookEntry->telNo      ) condition |= 1 << 1;
	if( phonebookEntry->name       ) condition |= 1 << 2;

И дальше переменную condition запихнуть в switch или вообще использовать в качестве индекса в массиве указателей? Мой случай ещё пограничный, но если добавить ещё один параметр, то вариантов уже будет 16! Короче, степень двойки. Я один такой упоротый или такое где-нибудь применяется?

 

u5er
()

Посоветуйте недо-NAS на коленке

Форум — Linux-hardware

Нашел в квартире свободное место в шкафу. Хочу запихнуть туда 4 жестких диска и еще какую-то железку сверху, чтобы раздавать кинчик по DLNA для телевизора и сливать туда фоточки с телефона, дабы не платить дяде за облако. Бонусом также думается заливать туда бакапы важного с локалхоста.

Как обычно, возникло несколько вопросов:

  1. В шкафу никакой особой вентиляции нет, поэтому хочется cpu/mb попрохладнее. Получается, что старые зионы с алиэкспресса отпадают. Что вообще недорогое выбрать?

  2. Диски хочу организовать в виде X физических разделов со, скажем, xfs, где будет храниться медиатека, которую не сильно страшно частично потерять в случае чего. Ну а для хранения важного объединить отдельные разделы с дисков в lvm mirror, а то и вовсе какой-нибудь ручной rsync настроить.

  3. Какие есть опенсорсные решения для синхронизации фото/видео альбомов со своими мобильными приложениями для айфонов? Можно, конечно, через ifuse ручками сливать, но это уже черезур гиковато, как по мне.

Перемещено hobbit из general

 

kawaii_neko
()

В чём делать презентации?

Форум — Desktop

LO Impress ужасен.

Ставить PowerPoint в Wine или есть ещё альтернативы?

 , powerpoint,

Harliff
()

Что из свободных решений может заменить WhatsApp и Telegram?

Форум — Talks

Давно не пользовался Jabber, плюс реализация некоторых функций может зависеть от клиента, поэтому лучше просто спрошу: есть ли в нём или в каком-то другом свободном мессенджере возможность простым образом создавать группы участников, которые не будут светиться в списке комнат и т.д.? То есть, условно говоря, создал чат, добавил людей - и они могут общаться, несмотря на то, что каждый может работать через свой личный сервер. Это можно сделать в Jabber? Или лучше посмотреть в сторону Matrix или другого варианта?

Перемещено maxcom из general

 , , ,

askh
()

pdf с полями ввода из tcl/tk

Форум — Development

Из программы на tcl/tk генерируется отчёт с текстом и картинками, затем экспортируется в pdf через библиотеку pdf4tcl (https://pdf4tcl.sourceforge.net/)

Облом когда понадобилось добавить поля ввода в pdf

pdf4tcl умеет добавлять такие поля (метод addForm), но система координат не совпадает

Хочется чтобы поля ввода были справа от Label1 и Label2

Кто виноват и что делать?

Минимальный тестовый фрагмент

#!/usr/bin/wish 

lappend auto_path [file join lib pdf4tcl094]
package require pdf4tcl

    set height 800
    set width  800

    canvas .canv -width $width -height $height 
    pack   .canv

    button .savePDF -text "save" -command savepdf
    pack .savePDF

	set font1 [font create -family Helvetica -size 10]

  .canv create text 0  0 -text "__________________________________________________________________________________________" -anchor w  -font $font1
  .canv create text 31  32 -text "Label 1 :" -anchor w -tag addform -font $font1
  .canv create text 90 450 -text "Label 2 :" -anchor w -tag addform -font $font1

proc savepdf {} {
    set fname {output.pdf}

    pdf4tcl::new mypdf -paper a4 -margin 15mm -compress 0

    mypdf startPage
    mypdf setFont 10 Helvetica
    mypdf canvas .canv
    foreach item [.canv find withtag addform] {
        set x [lindex [.canv bbox $item] 2]
        set y [lindex [.canv bbox $item] 3]
        puts "debug (x,y): $x,$y"
        mypdf addForm text [expr $x+20] $y 100 20 -init 0
    }
    mypdf write -file $fname
    mypdf destroy        

    exit 0
}

Вот полученный pdf

%PDF-1.4
5 0 obj
<<
/Length 6 0 R
>>
stream
/Helvetica 10 Tf
0 Tr
10 TL
q
1 w
[] 0 d
0 0 0 rg
0 0 0 RG
0 J
0 j
10.433 M
0.706317 0 0 -0.706317 43.226 793.83 cm
-1 -8 m
-1 459 l
721 459 l
721 -8 l
W
n
q
0 0 0 rg
BT
/Helvetica 17 Tf
0 Tr
17 TL
/Helvetica 14.388 Tf
0 Tr
14.388 TL
1 0 0 -1 0 4.079 Tm
(__________________________________________________________________________________________) Tj
ET
Q
q
0 0 0 rg
BT
/Helvetica 17 Tf
0 Tr
17 TL
/Helvetica 14.338 Tf
0 Tr
14.338 TL
1 0 0 -1 31 36.061 Tm
(Label 1 :) Tj
ET
Q
q
0 0 0 rg
BT
/Helvetica 17 Tf
0 Tr
17 TL
/Helvetica 14.338 Tf
0 Tr
14.338 TL
1 0 0 -1 90 454.061 Tm
(Label 2 :) Tj
ET
Q
Q

endstream
endobj

6 0 obj
599
endobj

4 0 obj
<</Type /Page
/Parent 2 0 R
/Resources 3 0 R
/Group <</S /Transparency /CS /DeviceRGB /I false /K false>>
/MediaBox [0 0 595 842]
/Contents [5 0 R]
/Annots [9 0 R
11 0 R]
>>
endobj

7 0 obj
<<
/Type /Font
/Subtype /Type1
/Encoding /WinAnsiEncoding
/Name /Helvetica
/BaseFont /Helvetica
>>
endobj
8 0 obj
<< /BBox [ 0 0 100 20] 
/Resources 3 0 R
/Subtype /Form
/Type /XObject

/Length 54
>>
stream
/Tx BMC BT /Helvetica 10 Tf 0 g 2 1.1 Td (0) Tj ET EMC
endstream
endobj
9 0 obj
<<
  /Subtype /Widget
  /P 4 0 R
  /Rect [149.52 738.48 249.52 758.48]
  /FT /Tx
  /T (textform8)
  /DA (/Helvetica 10 Tf 0 g)
  /Q 0
  /V (0)
  /AP << /N 8 0 R >>
  /F 4
>>

endobj
10 0 obj
<< /BBox [ 0 0 100 20] 
/Resources 3 0 R
/Subtype /Form
/Type /XObject

/Length 54
>>
stream
/Tx BMC BT /Helvetica 10 Tf 0 g 2 1.1 Td (0) Tj ET EMC
endstream
endobj
11 0 obj
<<
  /Subtype /Widget
  /P 4 0 R
  /Rect [208.52 320.48 308.52 340.48]
  /FT /Tx
  /T (textform10)
  /DA (/Helvetica 10 Tf 0 g)
  /Q 0
  /V (0)
  /AP << /N 10 0 R >>
  /F 4
>>

endobj
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
/AcroForm 12 0 R
>>
endobj

2 0 obj
<<
/Type /Pages
/Count 1
/Kids [4 0 R ]
>>
endobj

3 0 obj
<<
/ProcSet[/PDF /Text /ImageC]
/Font <<
/Helvetica 7 0 R
>>
>>
endobj

12 0 obj
<<
/Fields [9 0 R
11 0 R]
/DR 3 0 R
>>
endobj

xref
0 13
0000000000 65535 f 
0000001720 00000 n 
0000001787 00000 n 
0000001846 00000 n 
0000000686 00000 n 
0000000014 00000 n 
0000000666 00000 n 
0000000876 00000 n 
0000000990 00000 n 
0000001163 00000 n 
0000001353 00000 n 
0000001527 00000 n 
0000001926 00000 n 
trailer
<<
/Size 13
/Root 1 0 R
>>

startxref
1982
%%EOF

 , ,

futurama
()

FORTRAN зараза

Форум — Development
PROGRAM BALANCE
! Calculates balance after interest compounded
REAL BALANCE, INTEREST, RATE
BALANCE = 1000
RATE = 0.09
INTEREST = RATE * BALANCE
BALANCE = BALANCE + INTEREST
PRINT*, 'New balance:', BALANCE
END PROGRAM BALANCE

выдает такое

gfortran-7 balance.f
balance.f:1:1:

 PROGRAM BALANCE
 1
Error: Non-numeric character in statement label at (1)
balance.f:1:1:

 PROGRAM BALANCE
 1
Error: Unclassifiable statement at (1)
balance.f:3:1:

 REAL BALANCE, INTEREST, RATE
 1
Error: Non-numeric character in statement label at (1)
balance.f:3:1:

 REAL BALANCE, INTEREST, RATE
 1
Error: Unclassifiable statement at (1)
balance.f:4:1:

 BALANCE = 1000
 1
Error: Non-numeric character in statement label at (1)
balance.f:5:1:

 RATE = 0.09
 1
Error: Non-numeric character in statement label at (1)
balance.f:6:1:

 INTEREST = RATE * BALANCE
 1
Error: Non-numeric character in statement label at (1)
balance.f:7:1:

 BALANCE = BALANCE + INTEREST
 1
Error: Non-numeric character in statement label at (1)
balance.f:8:1:

 PRINT*, 'New balance:', BALANCE
 1
Error: Non-numeric character in statement label at (1)
balance.f:8:1:

 PRINT*, 'New balance:', BALANCE
 1
Error: Unclassifiable statement at (1)
balance.f:9:1:

 END PROGRAM BALANCE
 1
Error: Non-numeric character in statement label at (1)
balance.f:9:1:

 END PROGRAM BALANCE
 1
Error: Unclassifiable statement at (1)
f951: Error: Unexpected end of file in ‘balance.f’

какой fortran установить чтоб оно работало?

 

saufesma
()

Подсветка синтаксиса и радужная блевота

Форум — Development

Привет, ЛОР!

Как оказалось, не только меня выворачивает от большинства современных схем подсветки синтаксиса, которые подсвечивают любой элемент отдельным цветом, превращая код в радужную блевоту, через которую не видно собственно сам код.

Как минимум, интересный пост в тему: https://tonsky.me/blog/syntax-highlighting/

ЛОР, скажи, а какие есть годные темы, не страдающие от этого? Особенно интересует под Emacs. У меня пока есть достаточно короткий список: almost-mono-white/dark/gray, stimmung, tao, kuronami и, которой я сейчас пользуюсь, quartz (основана на alabaster от чувака выше).

В общем, кидай сюда, ЛОР, свою любимую тему подсветки, а мы её обосрём или одобрим.

 , , ,

hateyoufeel
()

Рисовалка битмапов на тикле

Форум — Development

Я тут под свои нужды накидал простенький редактор битмапок, который позволит кабанчиком рисовать небольшие пиктограммки. Получилось довольно неплохо и я решил поделиться им с сообществом. Код простой, поэтому легко будет подстроить под свои нужны.

Перемещение фукуса стрелочками. Для рисования/стирания пикселя используется пробел. По нажатию кнопки «Dump» в консоль выплёвывается последовательность 0 и 1 в виде текста, которую дальше можете сконвертировать в тот формат, который вам нужен.

Пример использования https://0x0.st/Kf8v.png

#!/usr/bin/wish

##########################
###   settings start   ###


set bitmapWidth  32
set bitmapHeight 32


###    settings end    ###
##########################

set currentFocusX 0
set currentFocusY 0

set verticalSymmetry   0
set horizontalSymmetry 0
set diagonalSymmetry   0


ttk::style layout pixel.TCheckbutton {
	Checkbutton.indicator
	Checkbutton.focus
}


proc focusUp { } {
	
	if { $::currentFocusY > 0 } {
		incr ::currentFocusY -1
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc focusDown { } {
	
	if { $::currentFocusY < [expr $::bitmapHeight - 1] } {
		incr ::currentFocusY
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc focusLeft { } {
	
	if { $::currentFocusX > 0 } {
		incr ::currentFocusX -1
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc focusRight { } {
	
	if { $::currentFocusX < [expr $::bitmapWidth - 1] } {
		incr ::currentFocusX
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc shiftUp { } {
	
	for { set rowNo 1 } { $rowNo < $::bitmapHeight } { incr rowNo } {
		
		set rowNoTo [expr $rowNo - 1]
		
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			set ::pixelr${rowNoTo}c${colNo} [ set ::pixelr${rowNo}c${colNo} ]
		}
	}
}

proc shiftLeft { } {
	
	for { set colNo 1 } { $colNo < $::bitmapWidth } { incr colNo } {
		
		set colNoTo [ expr $colNo - 1 ]
		
		for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
			set ::pixelr${rowNo}c${colNoTo} [ set ::pixelr${rowNo}c${colNo} ]
		}
	}
}
proc shiftRight { } {
	
	if { $::bitmapWidth < 2 } return
	
	for { set colNo [expr $::bitmapWidth - 2] } { $colNo >= 0 } { incr colNo -1 } {
		
		set colNoTo [ expr $colNo + 1 ]
		
		for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
			set ::pixelr${rowNo}c${colNoTo} [ set ::pixelr${rowNo}c${colNo} ]
		}
	}
}

proc shiftDown { } {
	
	if { $::bitmapHeight < 2 } return
	
	for { set rowNo [expr $::bitmapHeight - 2] } { $rowNo >= 0 } { incr rowNo -1 } {
		
		set rowNoTo [ expr $rowNo + 1 ]
		
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			set ::pixelr${rowNoTo}c${colNo} [ set ::pixelr${rowNo}c${colNo}]
		}
	}
}



proc setAllPixelsValue { value } {
	for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			set ::pixelr${rowNo}c${colNo} $value
		}
	}
}

proc verticalSymmetryHandler { rowNo colNo } {
	set mirrorCol [ expr $::bitmapWidth - $colNo - 1 ]
	set ::pixelr${rowNo}c${mirrorCol} [ set ::pixelr${rowNo}c${colNo} ]
}

proc horizontalSymmetryHandler { rowNo colNo } {
	set mirrorRow [ expr $::bitmapHeight - $rowNo - 1 ]
	set ::pixelr${mirrorRow}c${colNo} [ set ::pixelr${rowNo}c${colNo} ]
}

proc diagonalSymmetryHandler { rowNo colNo } {
	
	set diagonalRow [ expr $::bitmapWidth - $rowNo - 1 ]
	set diagonalCol [ expr $::bitmapWidth - $colNo - 1 ]
	
	set ::pixelr${diagonalRow}c${diagonalCol} [ set ::pixelr${rowNo}c${colNo} ]
}
 
proc symmetryHandler { rowNo colNo } {
	
	if { $::verticalSymmetry } {
		verticalSymmetryHandler $rowNo $colNo
	}
	
	if { $::horizontalSymmetry } {
		horizontalSymmetryHandler $rowNo $colNo
	}
	
	if { $::diagonalSymmetry } {
		diagonalSymmetryHandler $rowNo $colNo
	}
}

proc dumpPixelmap { } {
	
	puts ""
	
	for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			puts -nonewline [set ::pixelr${rowNo}c${colNo}]
		}
	}
	
	puts ""
	puts ""
}

proc buildCheckboxArea { } {
	
	for { set rowNo 0 } { $rowNo < 32 } { incr rowNo } {
		
		for { set colNo 0 } { $colNo < 32 } { incr colNo } {
			
			ttk::checkbutton .checkboxArea.pixelr${rowNo}c${colNo} -style pixel.TCheckbutton -variable pixelr${rowNo}c${colNo} -command "symmetryHandler $rowNo $colNo"
			grid .checkboxArea.pixelr${rowNo}c${colNo} -row $rowNo -column $colNo
			
			set ::pixelr${rowNo}c${colNo}  0
			
		}
	}
}


proc buildGui { } {
	
	set buttonsPaddingY 30
	
	# window layout
	ttk::frame .checkboxArea
	ttk::frame .controlPanel
	grid .checkboxArea  -row 0 -column 0 -padx 10 -pady 10
	grid .controlPanel  -row 0 -column 1 -padx 10 -pady 10
	
	#chechbox area build
	buildCheckboxArea
	
	#control panel
	
	#sel clear
	ttk::button .controlPanel.allClear -text "All clear" -command { setAllPixelsValue 0 }
	ttk::button .controlPanel.allSet   -text "All set"   -command { setAllPixelsValue 1 }
	
	grid .controlPanel.allClear -row 0 -column 0
	grid .controlPanel.allSet   -row 10 -column 0
	
	
	#shift panel
	ttk::frame .controlPanel.shift
	grid .controlPanel.shift  -row 20 -column 0 -pady $buttonsPaddingY
	
	
	ttk::button .controlPanel.shift.up    -text "/\\" -command shiftUp 
	ttk::button .controlPanel.shift.left  -text "<"   -command shiftLeft
	ttk::button .controlPanel.shift.right -text ">"   -command shiftRight
	ttk::button .controlPanel.shift.down  -text "\\/" -command shiftDown
	
	grid .controlPanel.shift.up    -row 0 -column 1
	grid .controlPanel.shift.left  -row 1 -column 0
	grid .controlPanel.shift.right -row 1 -column 2
	grid .controlPanel.shift.down  -row 2 -column 1
	
	
	#symmetry settings
	ttk::frame .controlPanel.symmetry
	grid       .controlPanel.symmetry -row 30 -column 0 -pady $buttonsPaddingY
	
	ttk::checkbutton .controlPanel.symmetry.vertical   -text "Вертикальная симметрия"   -variable verticalSymmetry
	ttk::checkbutton .controlPanel.symmetry.horizontal -text "Горизонтальная симметрия" -variable horizontalSymmetry
	ttk::checkbutton .controlPanel.symmetry.diagonal   -text "Диагональная симметрия" -variable diagonalSymmetry
	
	grid .controlPanel.symmetry.vertical   -pady 5
	grid .controlPanel.symmetry.horizontal -pady 5
	grid .controlPanel.symmetry.diagonal   -pady 5
	
	
	#dump
	ttk::button .controlPanel.dump     -text "Dump"      -command { dumpPixelmap }
	grid .controlPanel.dump     -row 100 -column 0 -pady $buttonsPaddingY
	
}



buildGui


bind . <KeyPress-Up>    { focusUp    }
bind . <KeyPress-Left>  { focusLeft  }
bind . <KeyPress-Down>  { focusDown  }
bind . <KeyPress-Right> { focusRight }

 , ,

u5er
()

Передача структуры в функцию на Си

Форум — Development
struct watch {
    struct in_addr ipaddress; // remote ip
    int port; //remote port
    char *pathname; //file to be watched
};
typedef struct watch watch_t;

// file change handler will be called 
// when an event happens
// with parameters: watch details and the 
// event that occurred  on that watch
typedef void (*filechangehandler_t)(watch_t, int); << -- передаем структуру

Почему этот код не дает ошибку? Ведь передается не указатель на структуру, а - структура. Разве такое разрешено в Си?

pacify
()

Изучить С

Форум — Talks

Всем привет! Надоели мне эти скриптовые аркадные языки, повесточка, докеро-голанги и тп, решил заняться изучением С. Тем более что вспомнил о том, что по факту это единственный язык который доставлял удовольствие.

Посоветуйте пожалуйста книгу, которую можно почитать и порешать оттуда заодно задачи если есть.

 , ,

NorthernBlow
()

fselect 0.9.1

Новости — Open Source
Группа Open Source

fselect — это консольная утилита для поиска файлов с помощью выражений, напоминающих SQL. В некоторых случаях может заменить традиционный find и написание развесистых скриптов с его использованием.

( читать дальше... )

>>> Репозиторий проекта на GitHub

 , , , ,

Pupseng
()

Написал эмулятор своего мобильника

Галерея — Скриншоты

Более чем два месяца назад заказал отладочные платы для своего хоббийного проекта, но они так и не пришли и хз, придут ли вообще. Разработка прошивки для него из-за этого застопорилась: писать «на воздух» я не особо люблю, а текущая клавиатура уже не отвечает моим требованиям - банально не хватает кнопок.

И тогда в голову начала приходить мысль - а не организовать ли мне эмулятор по типу того, который используется в Android Studio? Идея показалась мне классной, но останавливало отсутствие внятной документации по qemu, поэтому для реализации задумки предлагалось соснуть сурца. В какой-то момент я понял, что без полноценной клавиатуры я не смогу продолжить проект - банально нет всех нужных кнопок - было принято решение засучить рукава и попробовать.

В штатной поставке esp-idf есть qemu, но в ней особо не развернёшься, поэтому начал с простого - используя простое i2c устройство в качестве шаблона, создал заглушки для клавиатуры, контроллера модема и контроллера питания. Подключить их тоже не составило труда - код как раз на скриншоте. Обмен данными по шине i2c оказался очень простым: на эмулируемом устройстве есть всего 2 функции обратного вызова - для чтения и для записи. Таким образом, когда мастер пишет и читает, то просто подсовываем ему то, что он просит. Таким образом реализовать эмуляцию i2c устройств оказалось легче лёгкого.

Далее прерывания. Для эмуляции линий gpio в qemu используются линии прерываний. Тут вроде всё просто: на эмулируемом устройстве создаются выходные линии qemu_irq и далее они подключаются… куда? Вот тут меня ждала первая, пусть и лёгкая, задача. В самом начале я подключил линию irq клавиатуры на матрицу прерываний. Обработчик прерываний вызывался, но понять, на каком gpio оно произошло он не мог. Немного пораскинув мозгами и пососав сурца покопав исходники, я нашёл правильное место для подключения - матрица gpio. Как видите, в функциях read и write ничего нет, поэтому реализовать матрицу предлагается самостоятельно. Ожидаемо :) Реализовывается она очень просто. Сначала в матрице gpio создаются 40 входных и 40 выходных лини qemu_irq, которые будут отвечать за все gpio, которые есть у esp32. Далее создаются ещё 2 выходные линии qemu_irq, которые отвечают за обычные и non-maskable прерывания. Их я подключил к матрице прерываний на специально предусмотренные для этого каналы.

Теперь возвращаемся к функцуиям read и write. Вы когда-нибудь работали с расширителями портов, которые подключаются по шинам spi и i2c? Вся суть сводится к тому, что вы просто пишете и читаете нужные регистры по шинам, верно? Вот тут всё тоже самое, только с одним маленьким отличием - сами регистры нахадятся в самом микроконтроллере и процессор имеет к ним прямой доступ. То есть матрица gpio - это просто расширитель портов, который встроен в процессор и подключен напрямую к нему. Таким образом, вы теперь выступаете в качестве микросхемы :) В ваши регистры будут что-то писать и читать, а вы будете управлять линиями gpio. Когда процессор хочет выставить нужный gpio в нужный уровень - он просто пишет нужный бит в нужный регистр. Вы это видите и переключаете нужную линию qemu_irq в нужный уровень. Если же входная линия изменяет свой уровень, то вы просто отмечаете это у себя в структуре и при чтении сможете вернуть процессору текущие уровни gpio. Если процессор настроил прерывание на каком-либо gpio, то его можно уведомить об этом с помощью линий irq и nmi-irq. Далее процессор прочитает регистр прерываний и попросит вас сбросить их и вы это сделаете :) (иначе он будет постоянно опрашивать регистры прерываний, думая, что они всё ещё активны). Таким образом, реализовать матрицу gpio не составило особого труда. После этого я подключил свои устройства к нужным линиям матрицы gpio и смог эмулировать работу gpio без проблем.

Итак, я уже потирал руки и думал: «Сейчас я кабанчиком организую эмуляцию дисплея на шине spi и можно будет браться за гуй.». Ок, по аналогии с устройством i2c, беру в качестве шаблона какое-нибудь spi-устройство и начинаю реализовывать дисплей. Общение происходит как по i2c, только вместо обратных вызовов read и write, у вас есть обратный вызов transfer, в котором одновременно происходит и приём и передача данных. Сделал я дисплей, запускаю и… тишина! То есть по шине мне передаются сплошные нули! Всмысле? 0_0 В этот раз пососать сурца покопаться в исходниках пришлось гораздо более основательно. В итоге, понатыкав везде и всюду спасительный printf(), я нашёл чёрную дыру, в которой терялись данные по дороге от гостя до эмулируемого дисплея. На первый взгляд кажется, что тут всё ок, но когда я расставил printf() для распечатки адресов регистров, которые пишет и читает процессор, то всё встало на свои места - этот код никаким образом не обрабатывает регистры DMA! То есть вообще. Получается, что гость пытается слать данные через DMA буфер, а ванильный эмулятор spi туда даже не смотрит. В итоге, я сделал его копию и написал свою реализацию, которая позволяет отправлять данные по spi с использованием dma (полную реализацию пилить не стал, ибо влом). И для этого пришлось решить задачу со звёздочкой - доступ к памяти гостя.

Пару слов о том, как работает DMA на esp32. Прошивка организовывает где-нибудь в памяти специальные структуры с указателями на сами данные и входной буфер. Далее в специальнные DMA-регистры записываются адреса (указатели) этих структур. Далее подаётся команда на запуск передачи и данные передаются/принимаются без участия процессора. Теперь передо мной встала задача - как получить доступ по указателям, которые мне передаёт гость? Ведь гость даёт адрес внутри адресного пространства виртуальной машины. Сначала я нашёл решение с помощью функций cpu_physical_memory_read() и cpu_physical_memory_write(), которые работают с указателями из адресного пространства гостя. Но лишнее копирование не давало мне покоя и я нашёл решение получше.

При создании виртуальной машины qemu создаются различные области памяти. Одна из них - оперативка. Создаётся с помощью memory_region_init_ram(). В esp32 создаётся несколько различных областей такого типа. Фишка в том, что все эти области выделены как обычная память на хосте. Идея заключается в том, чтоб использовать memory_region_get_ram_ptr(), чтоб получить указатель на каждую область. Затем, зная начальный и конечный адрес каждого региона, можно вычислить расположение данных в оперативке хоста и работать с ними напрямую.

Последняя задача - как передать эти указатели, которые возвращают вызовы memory_region_get_ram_ptr(), в сам эмулятор spi? Он выполнен как отдельное устройство. В этот раз сосание сурца ковыряние в исходниках и чтение крох документации ничего не дали, поэтому решил действовать в лоб - передавать через свойства устройства. В эмуляторе spi я сделал несколько свойств с помощью object_property_add(), при создании машины при инициализации spi просто передал указатели как uint64_t с помощью qdev_prop_set_uint64(). Не уверен, что поступал правильно, но других решений не нашёл. Возможно, в таких случаях следует создавать отдельное устройство - эмулятор DMA, не знаю. Тем не менее, это сработало - я смог получить доступ к памяти гостя, высчитав смещение и прибавив его к одному из указателей на область памяти.

Гуй сделал на Tcl/Tk. Общение в машиной идёт через fifo. Просто и понятно. Уверен, что у qemu есть свой api для построения гуя, но я, честно говоря, к этому моменту уже окончательно устал искать информацию раз, и хотелось немного попрактиковаться в тикле два. До этого в тикле не работал с цветными изображениями и это был неплохой повод попробовать. Оказалось, что всё делается элементарно через image. Благо по тиклю информация есть, в отличие от.

К чему я вообще пишу обо всё об этом? Похвастаться? Да, не без этого, но ещё больше хочется поделиться вот чем. До того, как я полез писать эмулятор, я многое знал, но не понимал как именно работают те или иные вещи в микроконтроллерах. После того, как я написал эмулятор, я многое понял. Например, как именно процессор управляет своей перефирией. Как работают прерывания. Как работает DMA. Да и вообще, получил опыт в работе с «сырыми» регистрами. Я это к тому, что если у вас есть какая-нибудь идея и вам хочется её осуществить, то всегда пробуйте! Даже если задача изначально кажется сложной и неподъёмной. Запросто может оказаться так, что вы, как и я, не просто реализуете задуманное, но ещё получите ценные знания и/или опыт в процессе.

Такие дела \ё/

 , ,

u5er
()

Делаем любой терминал (и не только) выпадающим в системах на базе X11

Статьи — Desktop
Делаем любой терминал (и не только) выпадающим в системах на базе X11

Привет, ЛОР.
Многим знакома концепция выпадающего терминала, например yaquake или tilda.
Однако, простым скриптом можно сделать любой терминал (например, xfce4-terminal) выпадающим. Ограничения именно на терминалы нету – можно запускать таким образом почти любое приложение. Описанный в статье способ работает только на Xorg.

( читать дальше... )

 , ,

ann_lortemp2
()

Live дистрибутив для исследования железа?

Форум — Linux-install

Есть какой-нибудь специализированый дистрибутив, чтобы скачал на флешку/SSD и у тебя свежее ядро и куча всякого специфичного для бенчмарков, тестирования, сбора информации. Типа stress(ng), ramspeed, decode-dimms, acpidump и т.д.

Брать обычный Live и доустанавливать туда кучу пакетов не хочется, так как лень регулярно обновлять. Да ещё следить за актуальностью этих специальных утилит.

stresslinux вроде как мёртвый, а что-то подобное не гуглится.

Перемещено hobbit из general

 , , ,

mky
()