Connect Mikrobus OLED display with iMX 7 Board - embedded-linux

I have a i.MX7S board (WARP7) which has extension (Mikrobus standard) and an OLED C Click display (Mikrobus standard).
I try many ways but still failed to enable & display something on OLED screen.
Here are steps that I did:
Plug them together (with Mikrobus standard)
Bitbake and install "core-image-base" image (source code https://github.com/Freescale/fsl-community-bsp-platform -b krogoth)
Update linux kernel config with Staging/FBTFT module enabled all device (kernel source: https://github.com/WaRP7/linux-fslc)
Modify fbtft_device.c to add definition for my device
.name = "oledc",
.spi = &(struct spi_board_info) {
.modalias = "fb_ssd1351",
.max_speed_hz = 20000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.width = 96,
.height = 96,
},
.bgr = true,
.gpios = (const struct fbtft_gpio []) {
{ "reset", 198 },
{ "dc", 200 },
{ "led", 199 },
},
.gamma = "0 2 2 2 2 2 2 2 " \
"2 2 2 2 2 2 2 2 " \
"2 2 2 2 2 2 2 2 " \
"2 2 2 2 2 2 2 3 " \
"3 3 3 3 3 3 3 3 " \
"3 3 3 3 3 3 3 3 " \
"3 3 3 4 4 4 4 4 " \
"4 4 4 4 4 4 4"
}
}
}
Update Device Tree (imx7s-warp.dts) to add SPI support
&ecspi2 {
fsl,spi-num-chipselects = <1>;
cs-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi2>;
status = "okay";
spidev#0 {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <20000000>;
spi-cs-high;
};
};
&iomuxc {
pinctrl-names = "default";
imx7s-warp {
pinctrl_ecspi2: ecspi2grp {
fsl,pins = <
MX7D_PAD_ECSPI2_MISO__GPIO4_IO22 0x00000014 /* MISO */
MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x00000014 /* MOSI */
MX7D_PAD_ECSPI2_SCLK__GPIO4_IO20 0x00000014 /* SCLK */
MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x00000014 /* CS1 */
>;
};
};
imx7d-sdb {
pinctrl_brcm_reg: brcmgrp {
fsl,pins = <
MX7D_PAD_SD2_WP__GPIO5_IO10 0x14 /* WL_REG_ON */
>;
};
pinctrl_gpio: gpiogrp {
fsl,pins = <
/*MX7D_PAD_ENET1_RGMII_RD1__GPIO7_IO1 0x14*/
MX7D_PAD_ENET1_RGMII_RD0__GPIO7_IO0 0x00000005 /* RST */
MX7D_PAD_ENET1_RGMII_RD1__GPIO7_IO1 0x00000005 /* INT */
MX7D_PAD_ENET1_RGMII_RD2__GPIO7_IO2 0x00000005 /* PWM2 */
>;
};
Rebuild zImage, imx7s-warp.dtb, imx7s-warp.dts & copy to Boot partition (ums 0 mmc 0 mode)
Rebuild & install all modules (ums 0 mmc 0 mode)
Reboot board
login and run command
modprobe fbtft
modprobe fb_ssd1351
modprobe fbtft_device name=oledc debug=3 busnum=1
modprobe dmesg -c
cp /dev/urandom > /dev/fb0
===> In result: my display still black :( but only power led of display is ON
Output of command
root#imx7s-warp:~# modprobe fbtft_device name=oledc debug=3 busnum=1
fbtft_device: module is from the staging directory, the quality is unknown, you have been warned.
fbtft_device: SPI devices registered:
fbtft_device: spidev spi1.0 20000kHz 8 bits mode=0x04
fbtft_device: 'fb' Platform devices registered:
fbtft_device: Deleting spi1.0
fb_ssd1351 spi1.0: fbtft_gamma_parse_str() str=
fb_ssd1351 spi1.0: 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4
fb_ssd1351 spi1.0: fbtft_request_gpios: 'reset' = GPIO198
fb_ssd1351 spi1.0: fbtft_request_gpios: 'dc' = GPIO200
fb_ssd1351 spi1.0: fbtft_request_gpios: 'led' = GPIO199
fb_ssd1351 spi1.0: fbtft_verify_gpios()
fb_ssd1351 spi1.0: init_display()
fb_ssd1351 spi1.0: fbtft_reset()
fb_ssd1351 spi1.0: set_var()
fb_ssd1351 spi1.0: Display update: 978 kB/s (18.394 ms), fps=0 (0.000 ms)
fb_ssd1351 spi1.0: set_gamma()
Console: switching to colour frame buffer device 12x12
graphics fb0: fb_ssd1351 frame buffer, 96x96, 18 KiB video memory, 4 KiB DMA buffer memory, fps=20, spi1.0 at 20 MHz
fbtft_device: GPIOS used by 'oledc':
fbtft_device: 'reset' = GPIO198
fbtft_device: 'dc' = GPIO200
fbtft_device: 'led' = GPIO199
fbtft_device: SPI devices registered:
fbtft_device: fb_ssd1351 spi1.0 20000kHz 8 bits mode=0x00
I suppose my display will enable and display something after these step, but it do not.
Did I make something wrong ?
Since I've never worked on embedded & Linux before, then i'm losing my way here.
It will be thankful very much with any help or direction
Thank you a lot.

Related

How to iterate n nested for loops each from 0 to n?

for example if n = 2
// Nested loop for all possible pairs
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// here i have to use, i, j
}
}
for example if n = 3
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
// here i have to use, i, j, k
But if n = k, then how to iterate n for loops each from 0 to n?
I tried a lot but am not able to come up with a solution.
Is there any way to do it? Please help.
Can you test it with recursive function like this :
int foo(int n, int level)
{
if(level == 0)
{
for(int i=0; i<n; i++){
//Do something
}
return someValue;
}
for(int i=0; i<n; i++){
foo(n, --level);
}
}
//Start it with level = n like this
foo(n,n);
You could use an array for the indexes.
int indexes[n] = {0}; //initialize the whole array to zero
while {
//use indexes[0..n-1] as you would i, j, k, ...
indexes[n-1]++;
//propagate carry
for(i = n-1; i > 0; i--) {
if (indexes[i] == n) {
indexes[i-1]++;
indexes[i] = 0;
}
else break; //early exit from propagation, in case it's not necessary
}
if ( indexes[0] == n) break;
}
We can use the recursive solution ( with only a single loop and rest is the power of recursion ) , you just need to specify the depth and n where:
depth which specifies the level of nested for loops you want to use
n size of each loop
Below is the c++ implementation
#include <iostream>
#include <vector>
using namespace std;
void loop(int n, int depth, vector<int> &iteration){
if(!depth){
for(auto x:iteration)
cout<<x<<" ";
cout<<endl;
return;
}
for(int i=0;i<n;i++){
iteration[iteration.size()-depth] = i;
loop(n, depth-1, iteration);
}
}
int main(int argc, char const *argv[])
{
int depth = 3, n = 5;
vector<int> iteration(depth);
loop(n, depth, iteration);
return 0;
}
Output
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 1 0
0 1 1
0 1 2
0 1 3
0 1 4
0 2 0
0 2 1
0 2 2
0 2 3
0 2 4
0 3 0
0 3 1
0 3 2
0 3 3
0 3 4
0 4 0
0 4 1
0 4 2
0 4 3
0 4 4
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 1 0
1 1 1
1 1 2
1 1 3
1 1 4
1 2 0
1 2 1
1 2 2
1 2 3
1 2 4
1 3 0
1 3 1
1 3 2
1 3 3
1 3 4
1 4 0
1 4 1
1 4 2
1 4 3
1 4 4
2 0 0
2 0 1
2 0 2
2 0 3
2 0 4
2 1 0
2 1 1
2 1 2
2 1 3
2 1 4
2 2 0
2 2 1
2 2 2
2 2 3
2 2 4
2 3 0
2 3 1
2 3 2
2 3 3
2 3 4
2 4 0
2 4 1
2 4 2
2 4 3
2 4 4
3 0 0
3 0 1
3 0 2
3 0 3
3 0 4
3 1 0
3 1 1
3 1 2
3 1 3
3 1 4
3 2 0
3 2 1
3 2 2
3 2 3
3 2 4
3 3 0
3 3 1
3 3 2
3 3 3
3 3 4
3 4 0
3 4 1
3 4 2
3 4 3
3 4 4
4 0 0
4 0 1
4 0 2
4 0 3
4 0 4
4 1 0
4 1 1
4 1 2
4 1 3
4 1 4
4 2 0
4 2 1
4 2 2
4 2 3
4 2 4
4 3 0
4 3 1
4 3 2
4 3 3
4 3 4
4 4 0
4 4 1
4 4 2
4 4 3
4 4 4
Symbolically, you are generating all values of a base-n number of n digits. You perform this by starting from all zeroes and incrementing n^n times. Every time a digit reaches them, you reset it and carry to the next.
E.g. with n=3,
000 001 002 010 011 012 020 021 022 100 101 102 110 111 112 120 121 122 200 201 202 210 211 212 220 221 222
A possible implementation is with n counters.

How to increment by group

There is a table and now add a new column -- sort_num int default 0
id level sort_num
1 1 0
2 1 0
3 2 0
4 2 0
5 2 0
6 3 0
7 3 0
8 3 0
9 3 0
Now I want to set sort_num values like below
id level sort_num
1 1 1
2 1 2
3 2 1
4 2 2
5 2 3
6 3 1
7 3 2
8 3 3
9 3 4
The Java code implement above requirement is
int sortNum = 0;
int currentLevel = fooList.get(0).getLevel();
for (RuleConf foo : fooList) {
if(currentLevel != foo.getLevel()){
sortNum = 0;
currentLevel = foo.getLevel();
}
foo.setSortNum(++sortNum);
}
I want to know if Java8 could simplify above code?
PS. Use mysql to implement this requirement
set #index:=0; update t set sort_num = (#index:=#index+1) where level = 1 order by id;
set #index:=0; update t set sort_num = (#index:=#index+1) where level = 2 order by id;
set #index:=0; update t set sort_num = (#index:=#index+1) where level = 3 order by id;
The best approach is to stick to your plain enhanced for loop. I don't think it is possible to come up with a single Stream solution, since you need to have intermediate values. Like:
Map<Integer, List<RuleConf>> levels = fooList.stream()
.collect(Collectors.groupingBy(RuleConf::getLevel));
levels.values().forEach(v ->
IntStream.range(0, v.size()).forEach(i -> v.get(i).setSortNum(i + 1))
);
If you keep track of the next order numbers yourself, you may do it with one stream. This solution is thread safe as well, hence should work with parallel streams:
Map<Integer, AtomicInteger> orders = new ConcurrentHashMap<>();
fooList.stream().forEachOrdered(foo -> {
orders.putIfAbsent(foo.getLevel(), new AtomicInteger());
foo.setOrder(orders.get(foo.getLevel()).incrementAndGet());
});
It should outperform the other stream-solutions, because it requires to iterate over the list only ones.

Converting SFrames into input dataset Sframes

I have a pretty bad way to convert my input logs to the input dataset.
I have an SFrame sf with the following format:
user_id int
timestamp datetime.datetime
action int
reasoncode str
action column takes up 9 values ranging from 1 to 9.
So, every user_id can perform more than 1 action, more than once.
I am trying to obtain all unique user_id from sf and create an op_sf in the following manner:
y = 225
def calc_class(a,x):
diffd = a['timestamp'].apply(lambda x: (dte - x).days)
g = 0
b = 0
for i in diffd:
if i > y:
g += 1
else:
b += 1
if b>= x:
return 4
elif b!= 0:
return 3
elif g>= 0:
return 2
else:
return 1
l1 = []
ids = z['user_id'].unique()
for idd in ids:
temp = sf[sf['user_id']== idd]
zero1 = temp[temp['action'] == 1]
zero2 = temp[temp['action'] == 2]
zero3 = temp[temp['action'] == 3]
zero4 = temp[temp['action'] == 4]
zero5 = temp[temp['action'] == 5]
zero6 = temp[temp['action'] == 6]
zero7 = temp[temp['action'] == 7]
zeroh8 = temp[temp['reasoncode'] == 'xyz']
zero9 = temp[temp['reasoncode'] == 'abc']
/* I'm getting clas1 to clas9 from function calc_class for each action
clas1 to clas9 are 4 integers ranging from 1 to 4
*/
clas1 = calc_class(zero1,2)
clas2 = calc_class(zero2,2)
clas3 = calc_class(zero3,2)
clas4 = calc_class(zero4,2)
clas5 = calc_class(zero5,2)
clas6 = calc_class(zero6,2)
clas7 = calc_class(zero7,2)
clas8 = calc_class(zero8,2)
clas9 = calc_class(zero9,2)
l1.append([idd,clas1,clas2,clas3,clas4,clas5*(-1),clas6*(-1),clas7*(-1),clas8*(-1),clas9])
I wanted to know if this is the fastest way of doing this. Specifically if it is possible to do the same thing without generating the zero1 to zero9 SFrames.
An example sf:
user_id timestamp action reasoncode
574 23/09/15 12:43 1 None
574 23/09/15 11:15 2 None
574 06/10/15 11:20 2 None
574 06/10/15 11:21 3 None
588 04/11/15 10:00 1 None
588 05/11/15 10:00 1 None
555 15/12/15 13:00 1 None
585 22/12/15 17:30 1 None
585 15/01/16 07:44 7 xyz
588 06/01/16 08:10 7 abc
l1 corresponding to the above sf:
574 1 2 2 0 0 0 0 0 0
588 3 0 0 0 0 0 0 0 3
555 3 0 0 0 0 0 0 0 0
585 3 0 0 0 0 0 0 3 0
I think your logic is relatively complex, but it's still more efficient to use column-wise operations on the whole dataset, rather than extracting the subset of rows for each user. The key tools are SFrame.groupby, SFrame.apply, SFrame.unstack, and SFrame.unpack. API docs here:
https://dato.com/products/create/docs/generated/graphlab.SFrame.html
Here's a solution that uses slightly simpler data than your example and slightly simpler logic to code the old vs. new actions.
# Set up and make the data
import graphlab as gl
import datetime as dt
sf = gl.SFrame({'user': [574, 574, 574, 588, 588, 588],
'timestamp': [dt.datetime(2015, 9, 23), dt.datetime(2015, 9, 23),
dt.datetime(2015, 10, 6), dt.datetime(2015, 11, 4),
dt.datetime(2015, 11, 5), dt.datetime(2016, 1, 6)],
'action': [1, 2, 3, 1, 1, 7]})
# Count old vs. new actions.
sf['days_elapsed'] = (dt.datetime.today() - sf['timestamp']) / (3600 * 24)
sf['old_threshold'] = sf['days_elapsed'] > 225
aggregator = {'total_count': gl.aggregate.COUNT('user'),
'old_count': gl.aggregate.SUM('old_threshold')}
grp = sf.groupby(['user', 'action'], aggregator)
# Code the actions according to old vs. new. Use your own logic here.
grp['action_code'] = grp.apply(
lambda x: 2 if x['total_count'] > x['old_count'] else 1)
grp = grp[['user', 'action', 'action_code']]
# Reshape the results into columns.
sf_new = (grp.unstack(['action', 'action_code'], new_column_name='action_code')
.unpack('action_code'))
# Fill in zeros for entries with no actions.
for c in sf_new.column_names():
sf_new[c] = sf_new[c].fillna(0)
print sf_new
+------+---------------+---------------+---------------+---------------+
| user | action_code.1 | action_code.2 | action_code.3 | action_code.7 |
+------+---------------+---------------+---------------+---------------+
| 588 | 2 | 0 | 0 | 2 |
| 574 | 1 | 1 | 1 | 0 |
+------+---------------+---------------+---------------+---------------+
[2 rows x 5 columns]

Count the frequency of matrix values including 0

I have a vector
A = [ 1 1 1 2 2 3 6 8 9 9 ]
I would like to write a loop that counts the frequencies of values in my vector within a range I choose, this would include values that have 0 frequencies
For example, if I chose the range of 1:9 my results would be
3 2 1 0 0 1 0 1 2
If I picked 1:11 the result would be
3 2 1 0 0 1 0 1 2 0 0
Is this possible? Also ideally I would have to do this for giant matrices and vectors, so the fasted way to calculate this would be appreciated.
Here's an alternative suggestion to histcounts, which appears to be ~8x faster on Matlab 2015b:
A = [ 1 1 1 2 2 3 6 8 9 9 ];
maxRange = 11;
N = accumarray(A(:), 1, [maxRange,1])';
N =
3 2 1 0 0 1 0 1 2 0 0
Comparing the speed:
K>> tic; for i = 1:100000, N1 = accumarray(A(:), 1, [maxRange,1])'; end; toc;
Elapsed time is 0.537597 seconds.
K>> tic; for i = 1:100000, N2 = histcounts(A,1:maxRange+1); end; toc;
Elapsed time is 4.333394 seconds.
K>> isequal(N1, N2)
ans =
1
As per the loop request, here's a looped version, which should not be too slow since the latest engine overhaul:
A = [ 1 1 1 2 2 3 6 8 9 9 ];
maxRange = 11; %// your range
output = zeros(1,maxRange); %// initialise output
for ii = 1:maxRange
tmp = A==ii; %// temporary storage
output(ii) = sum(tmp(:)); %// find the number of occurences
end
which would result in
output =
3 2 1 0 0 1 0 1 2 0 0
Faster and not-looping would be #beaker's suggestion to use histcounts:
[N,edges] = histcounts(A,1:maxRange+1);
N =
3 2 1 0 0 1 0 1 2 0
where the +1 makes sure the last entry is included as well.
Assuming the input A to be a sorted array and the range starts from 1 and goes until some value greater than or equal to the largest element in A, here's an approach using diff and find -
%// Inputs
A = [2 4 4 4 8 9 11 11 11 12]; %// Modified for variety
maxN = 13;
idx = [0 find(diff(A)>0) numel(A)]+1;
out = zeros(1,maxN); %// OR for better performance : out(maxN) = 0;
out(A(idx(1:end-1))) = diff(idx);
Output -
out =
0 1 0 3 0 0 0 1 1 0 3 1 0
This can be done very easily with bsxfun.
Let the data be
A = [ 1 1 1 2 2 3 6 8 9 9 ]; %// data
B = 1:9; %// possible values
Then
result = sum(bsxfun(#eq, A(:), B(:).'), 1);
gives
result =
3 2 1 0 0 1 0 1 2

R - Making loops faster

This little code snippet is supposed to loop through a sorted data frame. It keeps a count of how many successive rows have the same information in columns aIndex and cIndex and also bIndex and dIndex. If these are the same, it deposits the count and increments it for the next time around, and if they differ, it deposits the count and resets it to 1 for the next time around.
for (i in 1:nrow(myFrame)) {
if (myFrame[i, aIndex] == myFrame[i, cIndex] &
myFrame[i, bIndex] == myFrame[i, dIndex]) {
myFrame[i, eIndex] <- count
count <- (count + 1)
} else {
myFrame[i, eIndex] <- count
count <- 1
}
}
It's been running for a long time now. I understand that I'm supposed to vectorize whenever possible, but I'm not really seeing it here. What am I supposed to do to make this faster?
Here's what an example few rows should look like after running:
aIndex bIndex cIndex dIndex eIndex
1 2 1 2 1
1 2 1 2 2
1 2 4 8 3
4 8 1 4 1
1 4 1 4 1
I think this will do what you want; the tricky part is that the count resets after the difference, which effectively puts a shift on the eIndex.
There (hopefully) is an easier way to do this, but this is what I came up with.
tmprle <- rle(((myFrame$aIndex == myFrame$cIndex) &
(myFrame$bIndex == myFrame$dIndex)))
myFrame$eIndex <- c(1,
unlist(ifelse(tmprle$values,
Vectorize(seq.default)(from = 2,
length = tmprle$lengths),
lapply(tmprle$lengths,
function(x) {rep(1, each = x)})))
)[-(nrow(myFrame)+1)]
which gives
> myFrame
aIndex bIndex cIndex dIndex eIndex
1 1 2 1 2 1
2 1 2 1 2 2
3 1 2 4 8 3
4 4 8 1 4 1
5 1 4 1 4 1
Maybe this will work. I have reworked the rle and sequence bits.
dat <- read.table(text="aIndex bIndex cIndex dIndex
1 2 1 2
1 2 1 2
1 2 4 8
4 8 1 4
1 4 1 4", header=TRUE, as.is=TRUE,sep = " ")
dat$eIndex <-NA
#identify rows where a=c and b=d, multiply by 1 to get a numeric vector
dat$id<-(dat$aIndex==dat$cIndex & dat$bIndex==dat$dIndex)*1
#identify sequence
runs <- rle(dat$id)
#create sequence, multiply by id to keep only identicals, +1 at the end
count <-sequence(runs$lengths)*dat$id+1
#shift sequence down one notch, start with 1
dat$eIndex <-c(1,count[-length(count)])
dat
aIndex bIndex cIndex dIndex eIndex id
1 1 2 1 2 1 1
2 1 2 1 2 2 1
3 1 2 4 8 3 0
4 4 8 1 4 1 0
5 1 4 1 4 1 1

Resources