Direct scrolling using Gtk::Viewport (gtkmm3) - gtk

I have a custom container which provides scrolling functionality by embedding a Gtk::Grid inside a Gtk::Viewport. The scrolling part works perfectly except for one glitch. Whenever an on_size_allocate event occurs it causes the property_value of the Gtk::Adjustment to reset to 0 causing the scroll position to jump to the top. Since this could happen when any of the children emits a queue resize or even when the top level window loses focus the scroll position sort of never stays where it should. By overriding the container's on_size_allocate handler I confirmed that the property_value of Gtk::Adjustment resets when I call the base class's on_size_allocate. Below is my on_size_allocate handler.
001 void CScrollGrid::on_size_allocate(Gtk::Allocation &oAlloc)
002 {
003 {
004 double dValue = m_refAdjustment->get_value();
005
006 std::cout << "size allocate (before), value: " << dValue << "\n";
007
008 Gtk::Widget::on_size_allocate(oAlloc);
009
010 std::cout
011 << "size allocate (after), value: "
012 << m_refAdjustment->get_value()
013 << "\n";
014
015 // Update scroll
016 {
017 int nMinimum;
018 int nDummy;
019
020 if (Gtk::ORIENTATION_VERTICAL
021 == m_eOrientation)
022 {
023 m_oGrid.get_preferred_height(nMinimum,
024 nDummy);
025 } else
026 {
027 m_oGrid.get_preferred_width(nMinimum,
028 nDummy);
029 }
030
031 m_refAdjustment->set_upper(nMinimum);
032 }
033
034 m_refAdjustment->property_value().set_value(dValue);
035
036 std::cout
037 << "size allocate (before fit), value: "
038 << m_refAdjustment->get_value()
039 << "\n";
040
041 Fit();
042 }
043 }
The stream output is as below.
size allocate (before), value: 146
size allocate (after), value: 0
size allocate (before fit), value: 0
At line 006 the stream output prints the correct 'value'. By line 010 the 'value' is reset to 0. As you can see that I have tried to apply the backed up value at line 034 but surprisingly the stream output at line 036 still returns 0! Looking at gtk_viewport_size_allocate (gtk code) I couldn't see anything obvious that relates to resetting of the Gtk::Adjustment.
What could cause the Gtk::Adjustment::property_value to stay stuck at 0 even after being set to a non-zero value?
What is the mechanism by which a Gtk::Viewport resets it's Gtk::Adjustments?
How can I prevent the Gtk::Adjustment::property_value from being reset like what's happening here?
NOTE: I didn't use Gtk::ScrolledWindow because of the following reason. The 'rows' inside the scrolled area could be of different heights. Irrespective of that the visible region needs to show the first and last row in full without clipping. When this is not possible, the last row is omitted and the extra space is converted as padding distributed evenly between top and bottom.

Figured out my mistake. Instead of calling the parent classes on_size_allocate I should have just called set_allocation. Also there is no need to update the Gtk::Adjustment's upper limit, Gtk::ViewPort does it internally. Following code works just fine.
001 void CScrollGrid::on_size_allocate(Gtk::Allocation &oAlloc)
002 {
003 set_allocation(oAlloc);
004
005 Fit();
006 }

Related

targets/stm32f1x.cfg:74: Error: target requires -dap parameter instead of -chain-position! OpenOCD

I am using OpenOCD to flash code into a black-pill (STM32f103). It worked a week ago but after updating ubuntu (it's the only thing I can think of that changed) it gives me an error when flashing the code.
Open On-Chip Debugger 0.11.0-rc2
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
WARNING: interface/stlink-v2-1.cfg is deprecated, please switch to interface/stlink.cfg
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
targets/stm32f1x.cfg:74: Error: target requires -dap parameter instead of -chain-position!
in procedure 'script'
at file "embedded:startup.tcl", line 26
at file "black_pill.cfg", line 24
at file "targets/stm32f1x.cfg", line 74
The stm32f1x.cfg file content:
# script for stm32f1x family
#
# stm32 devices support both JTAG and SWD transports.
#
source [find target/swj-dp.tcl]
source [find mem_helper.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME stm32f1x
}
set _ENDIAN little
# Work-area is a space in RAM used for flash programming
# By default use 4kB (as found on some STM32F100s)
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x1000
}
#jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
if { [using_jtag] } {
# See STM Document RM0008 Section 26.6.3
set _CPUTAPID 0x3ba00477
} {
# this is the SW-DP tap id not the jtag tap id
set _CPUTAPID 0x1ba01477
}
}
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
if { [info exists BSTAPID] } {
# FIXME this never gets used to override defaults...
set _BSTAPID $BSTAPID
} else {
# See STM Document RM0008
# Section 29.6.2
# Low density devices, Rev A
set _BSTAPID1 0x06412041
# Medium density devices, Rev A
set _BSTAPID2 0x06410041
# Medium density devices, Rev B and Rev Z
set _BSTAPID3 0x16410041
set _BSTAPID4 0x06420041
# High density devices, Rev A
set _BSTAPID5 0x06414041
# Connectivity line devices, Rev A and Rev Z
set _BSTAPID6 0x06418041
# XL line devices, Rev A
set _BSTAPID7 0x06430041
# VL line devices, Rev A and Z In medium-density and high-density value line devices
set _BSTAPID8 0x06420041
# VL line devices, Rev A
set _BSTAPID9 0x06428041
}
if {[using_jtag]} {
swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \
-expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \
-expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \
-expected-id $_BSTAPID6 -expected-id $_BSTAPID7 \
-expected-id $_BSTAPID8 -expected-id $_BSTAPID9
}
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
# flash size will be probed
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME
# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz
adapter_khz 1000
adapter_nsrst_delay 100
if {[using_jtag]} {
jtag_ntrst_delay 100
}
reset_config srst_nogate
if {![using_hla]} {
# if srst is not fitted use SYSRESETREQ to
# perform a soft reset
cortex_m reset_config sysresetreq
}
$_TARGETNAME configure -event examine-end {
# DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP |
# DBG_STANDBY | DBG_STOP | DBG_SLEEP
mmw 0xE0042004 0x00000307 0
}
$_TARGETNAME configure -event trace-config {
# Set TRACE_IOEN; TRACE_MODE is set to async; when using sync
# change this value accordingly to configure trace pins
# assignment
mmw 0xE0042004 0x00000020 0
}
I've tried changing the -chain-position for -dap but as I don't understand what I am doing it doesn't work.
Any help helping me understand this error would be highly appreciated.
Since version 0.11.0 OpenOCD doesn't create the DAP(Debug Access Point) isn't automatically created. Change the line for:
dap create dap_name -chain-position $_TARGETNAME
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap dap_name
For more information:
https://openocd.org/doc/html/TAP-Declaration.html#dapdeclaration

Interfacing TFT screen with STM32F446 using display bus interface

I'm trying to understand how to interface a TFT screen module with an STM32F4 chip on a custom PCB.
Here is the module and its basic info.
To write commands and data to the screen, the ILI9481 driver on the screen module uses the Display Bus Interface (DBI), where data is sent over 8 or 16 bits through data wires.
Looking at library examples, I understand (and please correct me, if I am wrong), that in order to send a command of one byte, it simply sets the digital pins of the chip high or low, depending on the command. For example, command 0x2 in 8bit communication would be 00000010, where 0 would be the digital low on the chips GPIO pin and 1 would be digital high, meaning 1 of 8 wires are active (logical high). I Hope, I understand this correctly.
Now as I looked over examples, usually these digital pins are on the same GPIO port. And if I understand correctly, GPIO ports have a register, called BSRR, where you can manipulate the logical levels of the pins of the GPIO port. If the data pins are all on the same GPIO port, I assume this would work (from the example, where c is the command byte):
void STM32_TFT_8bit::write8(uint8_t c) {
// BRR or BSRR avoid read, mask write cycle time
// BSRR is 32 bits wide. 1's in the most significant 16 bits signify pins to reset (clear)
// 1's in least significant 16 bits signify pins to set high. 0's mean 'do nothing'
TFT_DATA->regs->BSRR = ((~c)<<16) | (c); //Set pins to the 8 bit number
WR_STROBE;
}
However, on my PCB board, the data pins of the screen module are separated on different ports.
So, my question is, how would I do the same thing, send a command while manipulating the logical levels? I assume, that I could write set/reset my pins one by one, depending on the command, but how would it look with the BSRR registers?
If my data pins are as follows:
D0 -> PC12
D1 -> PC11
D2 -> PC10
D4 -> PA12
D5 -> PA11
D6 -> PA10
D7 -> PA9
Would a command of 0x9D (0b10011101) through the registers would look something like this? :
GPIOA->regs->BSRR = 0b0001101000000000; // A port: turn on PA9, PA11, PA12
GPIOC->regs->BSRR = 0b0001010000000000; // C port: turn on PC10 and PC12
how would it look with the BSRR registers?
A bitmask can be applied to the value that is written to the BSRR, for example like this:
/* set/reset selected GPIO output pins, ignore the rest */
static inline void _gpio_write(GPIO_TypeDef* GPIOx, uint16_t state, uint16_t mask)
{
GPIOx->BSRR = ((uint32_t)(~state & mask) << 16) | (state & mask);
}
The data bits need to be rearranged before writing them to the GPIO output registers, for example like this:
#define BITS(w,b) (((w) & (1 << (b))) >> (b))
/* write a data/command byte to the data bus DB[7:0] of custom ILI9481 board
used pin assignment: D0 -> PC12, D1 -> PC11, D2 -> PC10, (D3 -> PC1) (?)
D4 -> PA12, D5 -> PA11, D6 -> PA10, D7 -> PA9 */
static void _write_data_to_pins(uint8_t data)
{
const uint16_t mask_c = 1<<12 | 1<<11 | 1<<10 | 1<<1; /* 0x1c02 */
const uint16_t mask_a = 1<<12 | 1<<11 | 1<<10 | 1<<9; /* 0x1e00 */
_gpio_write(GPIOC, (uint16_t)(BITS(data, 0) << 12 | BITS(data, 1) << 11 |
BITS(data, 2) << 10 | BITS(data, 3) << 1), mask_c);
_gpio_write(GPIOA, (uint16_t)(BITS(data, 4) << 12 | BITS(data, 5) << 11 |
BITS(data, 6) << 10 | BITS(data, 7) << 9), mask_a);
}
Test:
/* just for testing: read the written data bits back and arrange them in a byte */
static uint8_t _read_data_from_pins(void)
{
const uint32_t reg_c = GPIOC->ODR;
const uint32_t reg_a = GPIOA->ODR;
return (uint8_t)(BITS(reg_c, 12) << 0 | BITS(reg_c, 11) << 1 |
BITS(reg_c, 10) << 2 | BITS(reg_c, 1) << 3 |
BITS(reg_a, 12) << 4 | BITS(reg_a, 11) << 5 |
BITS(reg_a, 10) << 6 | BITS(reg_a, 9) << 7);
}
/* somewhere in main loop of test project */
{
uint8_t d = 0xff;
do {
_write_data_to_pins(d);
if (d != _read_data_from_pins()) {
Error_Handler();
}
} while (d--);
}
(Note: Only 7 of the 8 data pins DB[7:0] were listed in the question, PC1 was assigned to data pin D3 here.)
(Note: Most of these bit-shifts can be easily optimized out by the compiler, use at least -O1 to get somewhat compact results with GCC.)
GPIOA->regs->BSRR = 0b0001101000000000; // A port: turn on PA9, PA11, PA12
GPIOC->regs->BSRR = 0b0001010000000000; // C port: turn on PC10 and PC12
These two code lines do what is stated in the comments. But they will leave all the other pins unchanged.
The resulting output will depend on the previous state of the output data register. - For the LOW data pins, the corresponding GPIO port bits in BSRR[31:16] need to be set to 1 in order to update all the 8-bit data bus lines at once.
To answer the actual question:
No, the output on the data bus will not be 0x9D (0b1001'1101) after writing the two quoted bit patterns to the two BSRR registers. - In my case, it would look like this (please correct me if I'm wrong):
/* write 0x9D (0b1001'1101) to the data bus
used pin assignment: D0 -> PC12, D1 -> PC11, D2 -> PC10, (D3 -> PC1) (?)
D4 -> PA12, D5 -> PA11, D6 -> PA10, D7 -> PA9 */
GPIOC->BSRR = 0x8001402; /* = 0b00001000'00000000'00010100'00000010 */
GPIOA->BSRR = 0xc001200; /* = 0b00001100'00000000'00010010'00000000 */
Suppose 'command' is the byte to send (I hope there is a strobe somewhere...).
I would simply make 8 lines of code like this (If I well understand the port registers of the STM32):
if (command & 1) GPIOC->BSRR |= 1 << 12; else GPIOC->BSRR &= ~(1 << 12);
if (command & 2) GPIOC->BSRR |= 1 << 11; else GPIOC->BSRR &= ~(1 << 11);
...
if (command & 128) GPIOA->BSRR |= 1 << 9; else GPIOA->BSRR &= ~(1 << 9);
Maybe this is quite raw, but it works and it is easy to understand (i.e. more difficult to make typos). Next time tell the hardware designer to arrange wires just a little better... it is hard to think at something worse than this, the bits seem reversed just to see if the software guy can cope with them!

How to change quantum in xv6? [duplicate]

Right now it seems that on every click tick, the running process is preempted and forced to yield the processor, I have thoroughly investigated the code-base and the only relevant part of the code to process preemption is below (in trap.c):
// Force process to give up CPU on clock tick.
// If interrupts were on while locks held, would need to check nlock.
if(myproc() && myproc() -> state == RUNNING && tf -> trapno == T_IRQ0 + IRQ_TIMER)
yield();
I guess that timing is specified in T_IRQ0 + IRQ_TIMER, but I can't figure out how these two can be modified, these two are specified in trap.h:
#define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ
#define IRQ_TIMER 0
I wonder how I can change the default RR scheduling time-slice (which is right now 1 clock tick, fir example make it 10 clock-tick)?
If you want a process to be executed more time than the others, you can allow it more timeslices, *without` changing the timeslice duration.
To do so, you can add some extra_slice and current_slice in struct proc and modify the TIMER trap handler this way:
if(myproc() && myproc()->state == RUNNING &&
tf->trapno == T_IRQ0+IRQ_TIMER)
{
int current = myproc()->current_slice;
if ( current )
myproc()->current_slice = current - 1;
else
yield();
}
Then you just have to create a syscall to set extra_slice and modify the scheduler function to reset current_slice to extra_slice at process wakeup:
// Switch to chosen process. It is the process's job
// to release ptable.lock and then reacquire it
// before jumping back to us.
c->proc = p;
switchuvm(p);
p->state = RUNNING;
p->current_slice = p->extra_slice
You can read lapic.c file:
lapicinit(void)
{
....
// The timer repeatedly counts down at bus frequency
// from lapic[TICR] and then issues an interrupt.
// If xv6 cared more about precise timekeeping,
// TICR would be calibrated using an external time source.
lapicw(TDCR, X1);
lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
lapicw(TICR, 10000000);
So, if you want the timer interrupt to be more spaced, change the TICR value:
lapicw(TICR, 10000000); //10 000 000
can become
lapicw(TICR, 100000000); //100 000 000
Warning, TICR references a 32bits unsigned counter, do not go over 4 294 967 295 (0xFFFFFFFF)

How do I print a string in one line in MARIE?

I want to print a set of letters in one line in MARIE. I modified the code to print Hello World and came up with:
ORG 0 / implemented using "do while" loop
WHILE, LOAD STR_BASE / load str_base into ac
ADD ITR / add index to str_base
STORE INDEX / store (str_base + index) into ac
CLEAR / set ac to zero
ADDI INDEX / get the value at ADDR
SKIPCOND 400 / SKIP if ADDR = 0 (or null char)
JUMP DO / jump to DO
JUMP PRINT / JUMP to END
DO, STORE TEMP / output value at ADDR
LOAD ITR / load iterator into ac
ADD ONE / increment iterator by one
STORE ITR / store ac in iterator
JUMP WHILE / jump to while
PRINT, SUBT ONE
SKIPCOND 000
JUMP PR
HALT
PR, OUTPUT
JUMP WHILE
ONE, DEC 1
ITR, DEC 0
INDEX, HEX 0
STR_BASE, HEX 12 / memory location of str
STR, HEX 48 / H
HEX 65 / E
HEX 6C / L
HEX 6C / L
HEX 6F / O
HEX 0 / carriage return
HEX 57 / W
HEX 6F / O
HEX 72 / R
HEX 6C / L
HEX 64 / D
HEX 0 / NULL char
My program ends up halting past two iterations. I can't seem to figure out how to print a set of characters in one line. Thanks.
Your value of STR_BASE is almost certainly incorrect. Based on what is here I would say it needs to be 18 instead of 12. Also you would either want to remove current null char that is between "HELLO" and "WORLD" and replace it with a space or simply remove that line, depending on your intended output.

Remove leading zeroes binary

I want to basically remove my leading zeroes. When I print out a number for example 17 is 00000 0000 0000 0000 0000 0000 00001 0001 but to do remove those leading zeroes. Because in sparc machine that is what is printed out and I need to do this using some sort of loop or logic or shift function.
this is my psuedocode for printing the binary
store input, %l1 ! store my decimal number in l1
move 1,%l2 !move 1 into l2 register
shift logical left l2,31,l2 !shift my mask 1 31 times to the left
loop:
and l2,l1,l3 ! do and logic between l1 and l2 and put this in l3
compare l3,0 compare l3 zero
bne print 1 !branch not equal to zero, to print 1
if equal to 0
print zero
print 1:
print a 1
go: increment counter
compare counter 32
if counter less than 32 return to loop
shift l2 to the right to continue comparison
so this is what is being done say my input is l1 is 17
00000 0000 0000 0000 0000 0000 00001 0001
10000 0000 0000 0000 0000 0000 00000 0000 and my mask 1 shift left 31 times
this pseucode print out my input decimal into binary. But how can I make it remove leading zeroes?
because in the sparc 17 input inside the machine is
0000 0000 0000 0000 0000 0000 0001 00001
You create the labels, like go and print 1 (more commonly done in all caps and without spaces, FYI). So, starting with bne you should always be printing 1, or falling through to see if it needs to print the 0:
! same initialization
mov 0, l4 ! Initialize a flag to avoid printing
LOOP:
and l2, l1, l3 ! do and logic between l1 and l2 and put this in l3
cmp l3, 0 ! Is this a 0 digit?
bne ALWAYS_PRINT ! If it's not 0, then it must be 1 (was "bne print 1")
cmp l4, 1 ! Should we be printing the 0?
be PRINT_VALUE ! Yes, we need to print the 0 because we have seen a 1
ba INCREMENT ! We should not be printing the 0, so check the next
! digit (ba is "branch always")
ALWAYS_PRINT: !
mov 1, %l4 ! Note that we want to always print for the
! rest of the loop
PRINT_VALUE: ! Do whatever you're doing to print values
print value in l3 ! Always print the value
INCREMENT: ! Formerly your "go:" label
! same logic
! AFTER LOOP IS DONE LOGIC
cmp l4, 0 ! If the flag was never set, then the value is 0
! Alternatively, you could just compare the value to 0
! and skip the loop entirely, only printing 0 (faster)
bne DO_NOT_PRINT ! If it was set (1), then do nothing
print zero ! If it wasn't set, then print the 0
DO_NOT_PRINT:
To walk through it a little, you need to continue to initialize your values and shift the bits to figure out what the current digit is for each iteration. Since you will need another flag, then you need to use another register that is initialized to an expected value (I chose 0, which commonly represents false).
Get current digit into l3 (0 or 1)
See if it is 0
If it's not 0, then it must be 1. So go remember that we found a 1, for later, then print the value and increment/loop.
If it's 0, then see if we have found a 1 before. If so, then print the value and increment/loop. If not, then increment/loop.
For actually printing, I have no idea what you are actually doing. However, you can avoid a second comparison by using the labels. For example, ALWAYS_PRINT will always be used when the value is 1, so you can just set the flag and immediately print 1, then jump to INCREMENT. If you did that, then PRINT_VALUE would only be used to print 0, which could then fall through to INCREMENT.
From a high level language's perspective, you want:
int l2 = // value...
bool seenOneAlready = false;
if (l2 != 0)
{
// MSB first
for (int i = 31; i > -1; --i)
{
int l3 = (l2 >> i) & 1;
if (l3 == 1)
{
seenOneAlready = true;
printf("1");
}
else if (seenOneAlready)
{
printf("0");
}
}
}
else
{
printf("0");
}